All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jadira.reflection.access.AbstractClassAccess Maven / Gradle / Ivy

There is a newer version: 7.0.0.CR1
Show newest version
package org.jadira.reflection.access;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

import org.jadira.reflection.access.api.ClassAccess;
import org.jadira.reflection.access.api.FieldAccess;
import org.jadira.reflection.access.api.MethodAccess;
import org.jadira.reflection.access.model.ClassModel;
import org.jadira.reflection.core.misc.ClassUtils;

public abstract class AbstractClassAccess implements ClassAccess {

	/**
	 * The class to be accessed
	 */
	private Class clazz;

	/**
	 * An ordered array giving the names of the fields in the class to accessed
	 */
	protected final String[] fieldNames;

	/**
	 * An ordered array giving the Fields in the class to accessed
	 */
	private final Field[] fields;

	private final FieldAccess[] fieldAccess;

	/**
	 * An ordered array giving the names of the methods in the class to accessed
	 */
    private final String[] methodNames;
	
	/**
	 * An ordered array giving the Methods in the class to accessed
	 */
    private final Method[] methods;
    
    private final MethodAccess[] methodAccess;

	private final ClassModel classModel;

	private final ClassAccess superClassAccess;

	private final boolean providesHashCode;
	private final boolean providesEquals;
	
	/**
	 * Constructor, intended for use by generated subclasses
	 * @param clazz The Class to be accessed
	 */
	@SuppressWarnings("unchecked")
	protected AbstractClassAccess(Class clazz) {

		this.clazz = clazz;

		Field[] myFields = ClassUtils.collectDeclaredInstanceFields(clazz);

		String[] unsortedFieldNames = new String[myFields.length];
		for (int i = 0; i < unsortedFieldNames.length; i++) {
			unsortedFieldNames[i] = myFields[i].getName();
		}
		fieldNames = Arrays.copyOf(unsortedFieldNames, unsortedFieldNames.length);
		Arrays.sort(fieldNames);

		final FieldAccess[] myFieldAccess = (FieldAccess[]) new FieldAccess[myFields.length];
		fields = new Field[myFields.length];

		for (int i = 0; i < fields.length; i++) {

			String fieldName = unsortedFieldNames[i];
			for (int tIdx = 0; tIdx < unsortedFieldNames.length; tIdx++) {
				if (fieldName.equals(fieldNames[tIdx])) {
					myFieldAccess[tIdx] = constructFieldAccess(myFields[i]);
					fields[tIdx] = myFields[i];
					break;
				}
			}

		}
		fieldAccess = myFieldAccess;
		
        Method[] myMethods = ClassUtils.collectDeclaredMethods(clazz);
        
        String[] unsortedMethodNames = new String[myMethods.length];
        for (int i=0; i < unsortedMethodNames.length; i++) {
            unsortedMethodNames[i] = myMethods[i].getName();
        }
        methodNames = Arrays.copyOf(unsortedMethodNames, unsortedMethodNames.length);
        Arrays.sort(methodNames);
        
        final MethodAccess[] myMethodAccess = (MethodAccess[])new MethodAccess[myMethods.length];
        methods = new Method[myMethods.length];
        
        for (int i=0; i < methods.length; i++) {
   
            String methodName = unsortedMethodNames[i];
            for (int tIdx = 0; tIdx < unsortedMethodNames.length; tIdx++) {
                if (methodName.equals(methodNames[tIdx])) {
                    myMethodAccess[tIdx] = constructMethodAccess(myMethods[i]);
                    methods[tIdx] = myMethods[i];
                    break;
                }
            }
        }
        methodAccess = myMethodAccess;
		
		final Class superClass = clazz.getSuperclass();
		if (superClass != null) {
			this.superClassAccess = constructClassAccess(clazz.getSuperclass());
		} else {
			this.superClassAccess = null;
		}
        
		this.classModel = ClassModel.get(this);
			
		Class hashcodeClass;
		try {
			hashcodeClass = clazz.getMethod("hashCode").getDeclaringClass();
		} catch (NoSuchMethodException e) {
			throw new IllegalStateException("hashCode() method could not be found: " + e.getMessage(), e);
		} catch (SecurityException e) {
			throw new IllegalStateException("hashCode() method could not be accessed: " + e.getMessage(), e);
		}
		
		providesHashCode = hashcodeClass.equals(clazz);
		
		Class equalsClass;
		try {
			equalsClass = clazz.getMethod("equals", Object.class).getDeclaringClass();
		} catch (NoSuchMethodException e) {
			throw new IllegalStateException("equals() method could not be found: " + e.getMessage(), e);
		} catch (SecurityException e) {
			throw new IllegalStateException("equals() method could not be accessed: " + e.getMessage(), e);
		}
		
		providesEquals = equalsClass.equals(clazz);
	}
	
	@Override
	public Class getType() {
		return clazz;
	}

	@Override
	public FieldAccess[] getDeclaredFieldAccessors() {
		return fieldAccess;
	}

	@Override
	public FieldAccess getDeclaredFieldAccess(Field f) {
		int idx = Arrays.binarySearch(fieldNames, f.getName());
		return fieldAccess[idx];
	}
	

    @Override
    public MethodAccess[] getDeclaredMethodAccessors() {
        return methodAccess;
    }
    
	@Override
	public MethodAccess getDeclaredMethodAccess(Method m) {
		int idx = Arrays.binarySearch(methodNames, m.getName());
		if (methodAccess[idx].method().equals(m)) {
			return methodAccess[idx];
		}
		int backTrack = idx;
		while (true) {
			if (methodAccess[backTrack].method().equals(m)) {
				return methodAccess[idx];
			}
			if (!(methodAccess[backTrack].method().getName()
					.equals(m.getName()))) {
				break;
			}
			backTrack = backTrack - 1;
		}
		while (true) {
			idx = idx + 1;
			if (methodAccess[idx].method().equals(m)) {
				return methodAccess[idx];
			}
			if (!(methodAccess[idx].method().getName().equals(m.getName()))) {
				break;
			}
		}
		return null;
	}
	
	@Override
	public ClassModel getClassModel() {
		return classModel;
	}

	protected String[] getDeclaredFieldNames() {
		return fieldNames;
	}
	
	protected Field[] getDeclaredFields() {
		return fields;
	}

	protected String[] getDeclaredMethodNames() {
		return methodNames;
	}
	
	protected Method[] getDeclaredMethods() {
		return methods;
	}
	
	@Override
	public ClassAccess getSuperClassAccess() {
		return superClassAccess;
	}
	

	@Override
	public boolean providesHashCode() {
		return providesHashCode;
	}
	
	@Override
	public boolean providesEquals() {
		return providesEquals;
	}
	
	protected abstract FieldAccess constructFieldAccess(Field field);
	
	protected abstract MethodAccess constructMethodAccess(Method method);
	
	protected abstract  ClassAccess constructClassAccess(Class clazz);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy