ValueAccessPointVariantSupport.java
package org.codefilarete.stalactite.engine.configurer;
import java.lang.reflect.Field;
import javax.annotation.Nullable;
import org.codefilarete.reflection.AccessorByField;
import org.codefilarete.reflection.AccessorChain;
import org.codefilarete.reflection.DefaultReadWritePropertyAccessPoint;
import org.codefilarete.reflection.ReadWriteAccessorChain;
import org.codefilarete.reflection.ReadWritePropertyAccessPoint;
import org.codefilarete.reflection.ReversibleAccessor;
import org.codefilarete.reflection.SerializablePropertyAccessor;
import org.codefilarete.reflection.SerializablePropertyMutator;
import org.codefilarete.tool.Reflections;
import org.codefilarete.tool.collection.Arrays;
import org.codefilarete.tool.function.ThreadSafeLazyInitializer;
/**
* Storage for different ways of declaring an attribute accessor: for each case, a constructor is available. Either by accessor, or mutator, or field.
* The output is a {@link ReadWritePropertyAccessPoint} based on the attribute accessor given at construction time. The resolution is made through
* {@link PropertyAccessorResolver}.
*
* @param <C> the owning type of the attribute
* @param <O> attribute type
* @author Guillaume Mary
*/
public class ValueAccessPointVariantSupport<C, O> {
private final ThreadSafeLazyInitializer<ReadWritePropertyAccessPoint<C, O>> accessor;
@Nullable
private SerializablePropertyAccessor<C, O> getter;
@Nullable
private SerializablePropertyMutator<C, O> setter;
// to be used in addition to getter or setter when attribute differs from method name (case when Java Naming Convention is not respected)
@Nullable
private Field field;
public ValueAccessPointVariantSupport(SerializablePropertyAccessor<C, O> getter) {
this.getter = getter;
this.accessor = new AccessorFieldLazyInitializer();
}
public ValueAccessPointVariantSupport(SerializablePropertyMutator<C, O> setter) {
this.setter = setter;
this.accessor = new AccessorFieldLazyInitializer();
}
public ValueAccessPointVariantSupport(Class persistedClass, String fieldName) {
this.accessor = new ThreadSafeLazyInitializer<ReadWritePropertyAccessPoint<C, O>>() {
@Override
protected ReadWritePropertyAccessPoint<C, O> createInstance() {
return new DefaultReadWritePropertyAccessPoint<>(new AccessorByField<>(Reflections.getField(persistedClass, fieldName)));
}
};
}
public void setField(Class persistedClass, String fieldName) {
this.field = Reflections.getField(persistedClass, fieldName);;
}
public ReadWritePropertyAccessPoint<C, O> getAccessor() {
return accessor.get();
}
public <X> ReadWritePropertyAccessPoint<X, O> shift(ReadWritePropertyAccessPoint<X, C> accessor) {
return new ReadWriteAccessorChain<>(AccessorChain.fromAccessorsWithNullSafe(Arrays.asList(accessor, getAccessor())));
}
/**
* Internal class that computes a {@link ReversibleAccessor} from getter or setter according to which one is set up
*/
private class AccessorFieldLazyInitializer extends ThreadSafeLazyInitializer<ReadWritePropertyAccessPoint<C, O>> {
@Override
protected ReadWritePropertyAccessPoint<C, O> createInstance() {
return new PropertyAccessorResolver<>(new PropertyAccessorResolver.AccessPointCoordinates<C, O>() {
@Override
public SerializablePropertyAccessor<C, O> getGetter() {
return ValueAccessPointVariantSupport.this.getter;
}
@Override
public SerializablePropertyMutator<C, O> getSetter() {
return ValueAccessPointVariantSupport.this.setter;
}
@Override
public Field getField() {
return ValueAccessPointVariantSupport.this.field;
}
}).resolve();
}
}
}