我有一個項目,它基於一個可能會更改的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;
}