1

我的问题涉及编写 JAXB 插件,尤其是ClassOutline内部插件。

里面有com.sun.tools.xjc.outline.ClassOutline字段:

  • 目标
  • 参考
  • 实现类
  • 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;

据我所知(所以回答):

  • 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创建新字段,然后执行CopyablePlugin并希望添加clone()复制每个字段的方法。但CopyablePlugin没有看到新生成的字段Plugin1- 因为要从使用方法中检索所有字段,如下所示ClassOutlineCopyablePlugincom.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.

它是错误还是功能?

现在我找到了解决方法。相同的字段也作为属性添加到target

classOutline.target.addProperty(prop);

问题

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

1 回答 1

1

我建议不要将字段添加到ClassOutline. 太晚了,也太麻烦了。相信我,我已经试过了。

我发现更容易和更优雅的是将属性添加到CClassInfo. 这是之前的一个阶段,在这里您可以操作模型。然后在下一步中,将从模型中生成轮廓,因此您甚至不必关心向ClassOutline.

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

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

现在回答你的问题。

  1. ref//通常都是刚刚生成的目标类implClassimplRef分离是由于 XJC 分别生成“公共接口”和“实现类”的一些生成方式。我不知道是什么implRef,JavaDoc 说了一些关于用户指定类的内容,所以我正在考虑jaxb:class/@ref绑定。不过,从来没有处理过。

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

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

  4. ClassOutline.getDeclaredFields()正确的,但它只为您提供在此类中声明的字段 - 没有来自超类的字段。但是递归地收集所有字段是非常简单的。 根据 的属性getDeclaredFields()生成s 。忘记,那只是. 所以“和的结合”没有多大意义。FieldOutlinetarget CClassInfoimplClassClassOutlinetargetimplClass

于 2018-02-12T20:24:08.817 回答