我有一个项目,它基于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;
}
答案 0 :(得分:1)
您可以使用JAXB模型而不是反射到JAXB类中。从类或包创建JAXB上下文时,它会创建这些类及其属性的基础模型。在运行时 - 基于注释。在编译期间(XJC) - 基于XML模式。
这是特定于实现的,所以我会把JAXB RI比MOXy更好。
JAXBContext
时,最后会得到JAXBContextImpl
的实例。getTypeInfoSet()
返回RuntimeTypeInfoSet
。RuntimeTypeInfoSet
是JAXB类,属性的完整和完整模型 - 您需要进行编组和解组。RuntimeClassInfo
)RuntimePropertyInfo
个实例
您可以分析这些结构,在运行时构建您的UI。它比挖掘反射容易得多。基本上这个Runtime...
的东西会完成所有必要的反射,所以你不必这样做。
顺便说一下,我个人不会在这里重新发明轮子,而是使用现有的模型驱动的UI生成方法之一,例如Metawidget。您必须将框架连接到JAXB模型,但它似乎比从头开始完成整个过程更容易。
大约7到8年前,我已经基于JAXB实现了XML Schema驱动的UI生成,这是一次冒险。有很多警告。