//020 8330 0577 bob
|
package com.awsle.aibatis.xml.engine.objecttree.reflection;
|
|
import com.awsle.aibatis.xml.engine.objecttree.ObjectAccessException;
|
import com.awsle.aibatis.xml.engine.objecttree.ObjectTree;
|
|
import java.lang.reflect.Field;
|
import java.lang.reflect.Modifier;
|
import java.util.LinkedList;
|
import java.util.List;
|
|
public class ReflectionObjectGraph implements ObjectTree {
|
|
private LinkedList fieldStack = new LinkedList();
|
private LinkedList instanceStack = new LinkedList();
|
private Class rootType;
|
private ObjectFactory objectFactory;
|
|
public ReflectionObjectGraph(Object root, ObjectFactory objectFactory) {
|
this.objectFactory = objectFactory;
|
init(root);
|
}
|
|
public ReflectionObjectGraph(Class rootType, ObjectFactory objectFactory) {
|
this.rootType = rootType;
|
this.objectFactory = objectFactory;
|
init(null);
|
}
|
|
private static class RootHolder {
|
Object value;
|
}
|
|
private void init(Object root) {
|
RootHolder holder = new RootHolder();
|
holder.value = root;
|
instanceStack.addLast(holder);
|
push("value");
|
}
|
|
public void push(String fieldName) {
|
Object top = instanceStack.getLast();
|
|
Field field = null;
|
Class currentClass = top.getClass();
|
try {
|
|
while (field == null) {
|
try {
|
field = currentClass.getDeclaredField(fieldName);
|
} catch (NoSuchFieldException e) {
|
if (Object.class.equals(currentClass)) {
|
throw new ObjectAccessException("Cannot access field " + fieldName, e);
|
}
|
currentClass = currentClass.getSuperclass();
|
}
|
}
|
|
} catch (SecurityException e) {
|
throw new ObjectAccessException("Cannot access field " + fieldName, e);
|
}
|
field.setAccessible(true);
|
fieldStack.addLast(field);
|
|
try {
|
instanceStack.addLast(field.get(top));
|
} catch (IllegalArgumentException e) {
|
throw new ObjectAccessException("Cannot access field " + fieldName, e);
|
} catch (IllegalAccessException e) {
|
throw new ObjectAccessException("Cannot access field " + fieldName, e);
|
}
|
|
}
|
|
public void pop() {
|
fieldStack.removeLast();
|
instanceStack.removeLast();
|
}
|
|
public Class type() {
|
if (fieldStack.size() == 1) {
|
return rootType;
|
} else {
|
Field field = (Field) fieldStack.getLast();
|
Class type = field.getType();
|
return type;
|
}
|
}
|
|
public Object get() {
|
return instanceStack.getLast();
|
}
|
|
public void set(Object value) {
|
try {
|
instanceStack.removeLast();
|
Field field = (Field) fieldStack.getLast();
|
Object top = instanceStack.getLast();
|
field.set(top, value);
|
instanceStack.addLast(value);
|
} catch (IllegalAccessException e) {
|
throw new ObjectAccessException("Cannot set field", e);
|
}
|
}
|
|
public void create(Class type) {
|
set(objectFactory.create(type));
|
}
|
|
public String[] fieldNames() {
|
List fieldNames = new LinkedList();
|
Class theClass = get().getClass();
|
Class currentClass = theClass;
|
|
while (!Object.class.equals(currentClass)) {
|
getFields(fieldNames, currentClass);
|
currentClass = currentClass.getSuperclass();
|
}
|
|
String[] result = new String[fieldNames.size()];
|
fieldNames.toArray(result);
|
return result;
|
}
|
|
private void getFields(List fieldNames, Class theClass) {
|
Field[] fields = theClass.getDeclaredFields();
|
for (int i = 0; i < fields.length; i++) {
|
Field field = fields[i];
|
int modifiers = field.getModifiers();
|
if (field.getName().startsWith("this$")) {
|
continue;
|
}
|
if (Modifier.isFinal(modifiers) ||
|
Modifier.isStatic(modifiers) ||
|
Modifier.isTransient(modifiers)) {
|
continue;
|
}
|
fieldNames.add(field.getName());
|
}
|
}
|
|
public ObjectTree newStack(Class type) {
|
return new ReflectionObjectGraph(type, objectFactory);
|
}
|
|
public ObjectTree newStack(Object instance) {
|
return new ReflectionObjectGraph(instance, objectFactory);
|
}
|
|
}
|