我有一个项目,它基于一个可能会更改的XML模式。模式使用JAXB转换为Java。模式的几个部分保证保持不变;特别是用户必须填写的表单的基本元素。一种在运行时查找另一个对象(包含列表)的所有子对象的方法
我想根据这个(被修改的)JAXB生成的代码生成一个表单。问题在于,因为我的代码是不变的,但架构可以随时更改,所以我不能在任何JAXB代码中硬编码,除了基本元素。
因此,我必须递归地找到基础对象下的所有元素。这并不是太麻烦,有一点反射魔力(找到所有对象的'getter'方法的返回类型,重复)。真正的问题是当我遇到一个列表。因为列表在运行时会丢失它们的类型,所以我无法确定列表包含的内容,并且无法进一步递归。
有没有人有解决这个问题的出色解决方案?我已经研究了大多数其他方式来在运行时保留列表类型,但没有任何工作。我很清楚,这可能是不可能的,但我想在放弃之前探索我的所有选择。如果还有其他方法可以做到这一点,我愿意尝试。
我当前的代码:
public static void getObjectDescendants(Object obj, int indent) throws Exception {
// Handle list of objects.
if (obj instanceof List) {
for(int i=0;i<indent;++i){System.out.print(" ");}
System.out.println("List");
Class<?> clazz = getListType((List<?>) obj); // Get type of object within list
// Create new object of that type from constructor. (temp solution)
Object object = clazz.getConstructor().newInstance();
getObjectDescendants(object, indent+1);
return;
}
// Handle regular object.
for (MethodDescriptor pd : Introspector.getBeanInfo(obj.getClass()).getMethodDescriptors()) {
// For each method this object has...
Method method = pd.getMethod();
// If it does not return a complex object, or a list, we don't care about it.
if (!method.getReturnType().toString().contains("JAXB.generated.object")
&& !method.getReturnType().toString().contains("java.util.List")) {
continue;
}
// Print out indent, and name of method.
for(int i=0;i<indent;++i){System.out.print(" ");}
System.out.println(method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()");
Object object;
try {
if (method.getReturnType().equals(List.class)) {
object = method.invoke(obj);
} else {
Constructor<?> constructor = method.getReturnType().getConstructor(String.class);
object = constructor.newInstance();
}
} catch (Exception e) {
continue; // Couldn't seem to handle this one.
}
getObjectDescendants(object, indent+1);
}
}
private static Class<?> getListType(final List<?> list) {
// Find out what object type is in the list, and return it.
Class<?> clazz = list.get(0).getClass(); // Doesn't work, since list is always empty.
return clazz;
}