org.jadira.reflection.access.AbstractClassAccess Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cloning Show documentation
Show all versions of cloning Show documentation
Cloning for Jadira Framework
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 super C> 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 super C> 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);
}