JAXB,XJC:生成类大纲的字段

时间:2018-01-17 14:34:23

标签: java jaxb xjc sun-codemodel jcodemodel

我的问题是关于编写JAXB插件,特别是ClassOutline内部。

com.sun.tools.xjc.outline.ClassOutline中有字段:

  • REF
  • implClass
  • implRef

代码:

/**
 * This {@link ClassOutline} holds information about this {@link CClassInfo}.
 */
public final @NotNull CClassInfo target;

/**
 * The exposed aspect of the a bean.
 *
 * implClass is always assignable to this type.
 * <p>
 * Usually this is the public content interface, but
 * it could be the same as the implClass.
 */
public final @NotNull JDefinedClass ref;

/**
 * The implementation aspect of a bean.
 * The actual place where fields/methods should be generated into.
 */
public final @NotNull JDefinedClass implClass;

/**
 * The implementation class that shall be used for reference.
 * <p>
 * Usually this field holds the same value as the {@link #implClass} method,
 * but sometimes it holds the user-specified implementation class
 * when it is specified.
 * <p>
 * This is the type that needs to be used for generating fields.
 */
public final @NotNull JClass implRef;

据我所知(CORS):

  • target - 保存Model中的信息,代表已解析和分析的模式文件(.xsd)
  • ref通常等于implClass并且都保持Code Model
  • implClass是放置新生成的字段,方法等的正确位置。
  • implRef - 它是什么?

我想将新字段添加到ClassOutline描述的类中,因此代码如下所示:

JDefinedClass dstClass = classOutline.ref;
JFieldVar dstField = dstClass.field(srcField.mods().getValue(),
                        srcField.type(), srcField.name());

它很有效,直到有另一个插件在上面的代码执行后运行并使用com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields()方法。

想象一下 - Plugin1创建新字段然后执行SO Answer并想要添加clone()方法,该方法会复制每个字段。但是CopyablePlugin没有看到Plugin1新生成的字段 - 因为从ClassOutline CopyablePlugin使用com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields()方法检索所有字段,如下所示:

/**
 * Gets all the {@link FieldOutline}s newly declared
 * in this class.
 */
public final FieldOutline[] getDeclaredFields() {
    List<CPropertyInfo> props = target.getProperties();
    // ...

请注意,getDeclaredFields()ClassOutline.target字段(这是Model - 已解析的XSD架构)中检索属性,并完全忽略生成的代码ClassOutline.implClass。< / p>

是错误还是功能?

目前我找到了解决方法。同一字段也作为属性添加到target

classOutline.target.addProperty(prop);

问题

  1. 你能解释一下,ref/implClass/implRef的作用是什么?
  2. 我应该在哪里生成全新的字段/方法?进入ref/implClass
  3. 是否有必要保持ref/implClasstarget之间的一致性?添加到implClass的新字段也应添加到target,对吧?
  4. com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields()是否正确?或者如何从ClassOutline中正确检索所有字段?也许这应该是targetimplClass内容的结合?

1 个答案:

答案 0 :(得分:1)

我建议不要在ClassOutline添加字段。太晚了,太麻烦了。相信我,我已经尝试过了。

我发现更容易,更优雅的是向CClassInfo添加属性。这是一个阶段,在这里你操纵模型。然后在下一步中,将从模型生成轮廓,这样您甚至不必关心向ClassOutline添加任何内容。

要向CClassInfo添加属性,只需实例化该属性(例如new CAttributePropertyInfo(...)),然后将其添加到CClassInfomyClassInfo.addProperty(myPropertyInfo);

对于Copyable插件,如果您的插件向模型添加属性并且您的插件在Copyable插件之前被调用,则后者将看到新添加的字段。这正是我建议扩充模型的原因,而不是破解大纲或代码模型。

现在回答你的问题。

  1. ref / implClass / implRef通常都只是目标生成的类。分离是由于XJC产生的一些代modi和公共接口&#34;和#34;实施课程&#34;分别。我不知道implRef是什么,JavaDoc说了一些关于用户指定类的内容,所以我想到了jaxb:class/@ref绑定。但是从来没有处理过它。

  2. 最好是扩充模型(如果要添加新属性/字段)。如果您想添加一些与模型无关的代码(例如clone插件中的Copyable方法),我只需将其添加到classOutline.implClass

  3. 从技术上讲,无需保持代码模型(classOutline.implClass)和模型(classOutline.target)同步。如果你不这样做,这不会打破XJC。我可以想象这可能会破坏一些XJC插件。例如,插件可以迭代JDefinedClass中的字段并尝试查找相应的模型属性。但危险是理论上的。

  4. ClassOutline.getDeclaredFields() 正确,但它只为您提供此类中声明的字段 - 没有来自超类的字段。但是递归地收集所有字段是非常微不足道的。 getDeclaredFields()根据FieldOutline target中的属性生成CClassInfo个。 忘记implClass,这只是ClassOutline的代表。 所以&#34; targetimplClass&#34;的结合没有多大意义。