PropertyAccessor.java
package org.codefilarete.reflection;
import org.danekja.java.util.function.serializable.SerializableBiConsumer;
import org.danekja.java.util.function.serializable.SerializableFunction;
import org.codefilarete.tool.function.Predicates;
/**
* A class for managing accesses (reading and writing) of a bean property.
*
* @author Guillaume Mary
* @see Accessors
*/
public class PropertyAccessor<C, T> implements ReversibleAccessor<C, T>, ReversibleMutator<C, T> {
/**
* Static constructor, because its signature would conflict with the one with {@link Accessor}, {@link Mutator}
* @param accessor a method reference to a getter
* @param mutator a method reference to a setter
* @param <C> bean type
* @param <T> property type
* @return a {@link PropertyAccessor} that will access a property through the given getter and getter
*/
public static <C, T> PropertyAccessor<C, T> fromMethodReference(SerializableFunction<C, T> accessor, SerializableBiConsumer<C, T> mutator) {
return new PropertyAccessor<>(new AccessorByMethodReference<>(accessor), new MutatorByMethodReference<>(mutator));
}
private final Accessor<C, T> accessor;
private final Mutator<C, T> mutator;
public PropertyAccessor(ReversibleAccessor<C, T> accessor) {
this(accessor, accessor.toMutator());
}
public PropertyAccessor(ReversibleMutator<C, T> mutator) {
this(mutator.toAccessor(), mutator);
}
public PropertyAccessor(Accessor<C, T> accessor, Mutator<C, T> mutator) {
this.accessor = accessor;
this.mutator = mutator;
}
public Accessor<C, T> getAccessor() {
return accessor;
}
public Mutator<C, T> getMutator() {
return mutator;
}
/**
* Shortcut for {@link #getAccessor()}.get(c)
* @param c the source instance
* @return the result of the invocation of the accessor onto c argument
*/
@Override
public T get(C c) {
return this.accessor.get(c);
}
/**
* Shortcut for {@link #getMutator()}.set(c, t)
* @param c the source instance
* @param t the argument of the setter
*/
public void set(C c, T t) {
this.mutator.set(c, t);
}
/**
* Same as {@link #getAccessor()}
* @return {@link #getAccessor()}
*/
@Override
public Accessor<C, T> toAccessor() {
return getAccessor();
}
/**
* Same as {@link #getMutator()}
* @return {@link #getMutator()}
*/
@Override
public Mutator<C, T> toMutator() {
return getMutator();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof PropertyAccessor)) {
return super.equals(obj);
} else {
return Predicates.equalOrNull(this.getAccessor(), ((PropertyAccessor) obj).getAccessor())
&& Predicates.equalOrNull(this.getMutator(), ((PropertyAccessor) obj).getMutator());
}
}
@Override
public int hashCode() {
// Implementation based on both accessor and mutator. Accessor is taken first but it doesn't matter
return 31 * getAccessor().hashCode() + getMutator().hashCode();
}
/**
* Implemented for trace in errors or debug
* @return the getter description if available, else defaults to super.toString()
*/
@Override
public String toString() {
return "property accessor by " + (getAccessor() instanceof AbstractAccessor
? ((AbstractAccessor<C, T>) getAccessor()).getGetterDescription()
: getAccessor().toString());
}
}