2015-04-08 26 views
0

我有一个项目,它基于一个可能会更改的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; 
} 

回答

1

而是与反射进入JAXB类的,你可以使用JAXB模式。当您从类或包创建JAXB上下文时,它会创建这些类及其属性的基础模型。在运行时 - 基于注释。在编译期间(XJC) - 基于XML模式。

这是针对具体实现的,所以我会带JAXB RI,因为我知道它比MOXy好。

  • 当您使用JAXB RI创建JAXBContext时,您会在末尾获得JAXBContextImpl的实例。
  • 这有一个方法getTypeInfoSet()返回RuntimeTypeInfoSet的实例。
  • 这个RuntimeTypeInfoSet是JAXB类的全部完整模型,属性 - 你需要编组和解组。
  • 对于复杂类型你必须RuntimeClassInfo情况下,其具有的属性(RuntimePropertyInfo

您可以分析这些结构的建立在运行时你的UI。这比挖掘反思容易得多。基本上这个Runtime...的东西做了所有必要的反映,所以你不必这样做。顺便说一句,我个人不会在这里重新发明轮子,并且可以使用现有的模型驱动的UI生成方法之一,例如Metawidget。你必须将框架连接到JAXB模型,但它似乎比从头开始整个事情更容易。大约7-8年前,我已经实现了基于JAXB的基于XML Schema驱动的UI生成,这真是一次冒险。有很多警告。

相关问题