代码之家  ›  专栏  ›  技术社区  ›  jsosnowski

JAXB、XJC:生成字段到类大纲

  •  1
  • jsosnowski  · 技术社区  · 8 年前

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

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

    • 目标
    • 裁判
    • 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;
    

    据我所知( SO Answer ):

    • target -在中保存信息 Model ,表示已解析和分析的架构文件(.xsd)
    • ref 通常等于 implClass 两者都成立 Code Model
    • implClass类 是放置新生成的字段、方法等的正确位置。
    • implRef -这是什么?

    我想向所描述的类添加新字段 类大纲 ,因此代码如下所示:

    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 看不到新生成的字段 插件1 -因为要从中检索所有字段 类大纲 这个 可复制插件 使用 通用域名格式。太阳工具。xjc。概述类大纲。getDeclaredFields() 方法,如下所示:

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

    请注意 getDeclaredFields() 从检索属性 ClassOutline.target 字段(这是 模型 -已解析的XSD架构),并完全忽略生成的代码 ClassOutline.implClass .

    这是一个bug还是一个特性?

    现在我找到了解决办法。该字段也作为属性添加到 目标 :

    classOutline.target.addProperty(prop);
    

    问题

    1. 你能解释一下吗 ref/implClass/implRef ?
    2. 我应该在哪里生成全新的字段/方法?进入 ref/implClass ?
    3. 是否有必要保持 参考/implClass 目标 ? 添加到的新字段 implClass类 还应添加到 目标 正当
    4. 通用域名格式。太阳工具。xjc。概述类大纲。getDeclaredFields() 对的或者如何正确地从ClassOutline检索所有字段?也许这应该是 目标 implClass类 所容纳之物
    1 回复  |  直到 8 年前
        1
  •  1
  •   lexicore    8 年前

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

    我发现更简单、更优雅的方法是将属性添加到 CClassInfo . 这是前面的一个阶段,在这里您可以操纵模型。然后在下一步中,将从模型中生成大纲,因此您甚至不必关心向 类大纲 .

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

    在以下情况下: Copyable 插件,如果您的插件向模型添加属性,并且在 可复制的 插件,后者将看到新添加的字段。这正是为什么我建议增强模型,而不是破坏大纲或代码模型。

    现在回答你的问题。

    1. ref / implClass / implRef 通常都只是目标生成的类。这种分离是由于某些生成modi造成的,其中XJC分别生成了“公共接口”和“实现类”。我不知道是什么 implRef公司 JavaDoc说明了一些关于用户指定类的内容,所以我想 jaxb:class/@ref 结合但从未处理过。

    2. 最好是扩充模型(如果您想添加新的属性/字段)。如果您想添加一些与模型无关的代码(如 clone 方法来自 可复制的 插件),I'l just add it to classOutline.implClass .

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

    4. ClassOutline.getDeclaredFields() 对的 ,但它只提供此类中声明的字段,而不提供超类中的字段。但是递归地收集所有字段是非常简单的。 getDeclaredFields() 生产 FieldOutline 基于的属性 target CClassInfo . 忘记 implClass类 ,这只是 类大纲 . So“联合 目标 implClass类 “没有多大意义。

    推荐文章