AccessorByField.java

package org.codefilarete.reflection;

import java.lang.reflect.Field;

import org.codefilarete.tool.Reflections;

/**
 * Property reader through its {@link Field}
 *
 * @author Guillaume Mary
 */
public class AccessorByField<C, T> extends AbstractAccessor<C, T>
		implements AccessorByMember<C, T, Field>, ReversibleAccessor<C, T>, ValueAccessPointByField {
	
	private final Field field;
	private final Mutator<C, T> mutator;
	
	public AccessorByField(Field field) {
		Reflections.ensureAccessible(field);
		this.field = field;
		// since MutatorByField instantiation has no cost we do it now to avoid lazy initialization which is always tricky
		this.mutator = new MutatorByField<>(field, this);
	}
	
	/**
	 * Internal (package private) constructor that doesn't ensure field accessibility.
	 * Made to avoid lazy initialization in {@link MutatorByField}.
	 *
	 * @param field the field to write to
	 */
	AccessorByField(Field field, Mutator<C, T> mutator) {
		this.field = field;
		this.mutator = mutator;
	}
	
	@Override
	public Field getGetter() {
		return this.field;
	}
	
	@Override
	public Field getField() {
		return getGetter();
	}
	
	@Override
	public Class<T> getPropertyType() {
		return (Class<T>) field.getType();
	}
	
	@Override
	protected T doGet(C c) throws IllegalAccessException {
		return (T) getGetter().get(c);
	}
	
	@Override
	public String getGetterDescription() {
		return "accessor for field " + Reflections.toString(getGetter());
	}
	
	@Override
	public Mutator<C, T> toMutator() {
		return this.mutator;
	}
	
	@Override
	public boolean equals(Object other) {
		// we base our implementation on the getter String because a setAccessible() call on the member changes its internal state
		// and I don't think it sould be taken into account for comparison
		return this == other
				|| (other instanceof AccessorByField && getGetter().toString().equals(((AccessorByField) other).getGetter().toString()));
	}
	
	@Override
	public int hashCode() {
		return getGetter().hashCode();
	}
}