我的问题是关于编写JAXB插件,特别是JAXB代码模型。
ClassOutline
(以及它是companions)和JClass
(以及companions)和CClass
(以及companions)的作用是什么?在查看相应包中的类列表时,不清楚什么是鸡,什么是鸡蛋。
我的解释是CClass
(CPropertyInfo
,CEnumConstant
,...)是由XJC在XSD初稿解析时创建的。然后发生了一些魔法,并将此模型转换为JClass
(JFieldVar
,JEnumConstant
,...),并在此转换过程中应用自定义。然后调用插件。 ClassOutline
用作这两个模型之间的桥梁。总之看起来很复杂。
通过这些并行模型,我相信可以通过多种方式获得相同的信息。例如,类字段类型:
JClass#fields()
→JFieldVar#type
→JType
CClassInfo#getProperties()
→CPropertyInfo#baseType
→JType
我正在寻找上述模型生命周期的详细解释。感谢。
答案 0 :(得分:18)
哦,哦,有人对XJC内部感兴趣。我可能会有所帮助,因为我可能开发了比其他任何人更多的JAXB插件(例如,参见JAXB2 Basics)
好的,我们开始吧。在XJC中,模式编译器大致遵循
让我们从最后两个开始。
我希望Java文件不需要解释。
代码模型也是一件相对简单的事情。它是一个可用于以编程方式构造Java代码的API。你可以只使用字符串连接,但它更容易出错。使用CodeModel,您几乎可以保证获得至少语法正确的Java代码。所以我希望这一部分也很清楚。 (顺便说一下,我非常喜欢CodeModel。我最近根据CodeModel的想法写了JavaScript Code Model。)
现在让我们来看看“模型”和“大纲”。 模型是解析传入模式的结果。它模拟传入模式的结构,主要是对应于复杂类型的“类”和对应于元素,属性和值的“属性”(例如,当你有一个简单内容的复杂类型时)。
应该将模型理解为接近XML和模式的逻辑建模构造。因此,它只描述了它们具有的类型和属性。我描述它的方式肯定要复杂得多,有各种例外和警告 - 从wilcard类型(xsd:any),替换组,枚举,内置类型等开始。
非常有趣的是,Model
的兄弟是RuntimeTypeInfoSetImpl
,JAXB在运行时使用它。所以它也是一种模型 - 然而,它不是从XML Schema中解析而是从类中的JAXB注释中解析出来的。这个概念是一样的。 Model和RuntimeTypeInfoSetImpl
都实现了TypeInfoSet
接口,这是一个超级构造。检查ClassInfo
和PropertyInfo
等接口 - 它们是针对编译时(XJC中的CClassInfo
和CPropertyInfo
)和运行时(RuntimeClassInfoImpl
等)实现的。对于JAXB RI)。
好的,所以当XJC解析并分析了架构时,你就得到了Model
。此Model
无法生成代码。实际上,有不同的生成代码的策略。您可以生成带注释的类,也可以像在JAXB 1中一样生成接口/实现类对。整个代码生成实际上并不是模型的任务。此外,有许多方面与Java代码的物理特性相关,但与模型并不真正相关。例如,您必须将类分组到包中。这是由Java的打包系统驱动的,而不是由模型本身的属性驱动的。
这就是轮廓发挥作用的地方。您可以在架构模型和代码模型之间看到大纲。您可以将轮廓视为负责组织代码和从JDefinedClass
生成CClassInfo
es的代码模型元素的工厂。
所以你是对的,确实非常复杂。我不是Sun / Oracle员工,我没有设计它(我知道做过它的人,但非常尊重他)。 我可以猜出某些设计决策的几个原因,例如:
我同意这种设计非常复杂,但它有其原因。一个证明就是实际上可以构建用于XML到JavaScript映射的映射生成器 - 基本上在相同的模型上。我只需要替换代码生成,使模式分析完整无缺。 (请参阅Jsonix。)
好的,希望我能说明为什么XJC中的事情是这样的。祝你好运这些API,它们并非直截了当。随意检查现有的开源代码,有很多可用的例子。
PS。真的一直想写这个。 :)
答案 1 :(得分:2)
(这是为了回答你的进一步问题。)
是的,可以检查自定义项。 Here is我用来访问自定义项的类。
技巧是引用属性没有自己的自定义,自定义放在引用的元素属性中。
public static CCustomizations getCustomizations(
final CPropertyInfo propertyInfo) {
final CCustomizations main = new CCustomizations(
propertyInfo.getCustomizations());
final Collection<CCustomizations> elementCustomizations = propertyInfo
.accept(new CPropertyVisitor<Collection<CCustomizations>>() {
public Collection<CCustomizations> onAttribute(
CAttributePropertyInfo info) {
return Collections.emptyList();
}
public Collection<CCustomizations> onElement(
CElementPropertyInfo arg0) {
return Collections.emptyList();
}
public Collection<CCustomizations> onReference(
CReferencePropertyInfo info) {
final List<CCustomizations> elementCustomizations = new ArrayList<CCustomizations>(
info.getElements().size());
for (CElement element : info.getElements()) {
if (!(element instanceof CElementInfo && ((CElementInfo) element)
.hasClass())) {
elementCustomizations.add(element
.getCustomizations());
}
}
return elementCustomizations;
}
public Collection<CCustomizations> onValue(
CValuePropertyInfo arg0) {
return Collections.emptyList();
};
});
CCustomizations customizations = main;
for (CCustomizations e : elementCustomizations) {
main.addAll(e);
}
return customizations;
}
我认为users@jaxb.java.net是进行此类讨论的好地方。