8

私の質問は、JAXB プラグイン、特に JAXB コードモデルの作成に関するものです。

ClassOutline(およびその仲間) とJClass(および仲間) とCClass(および仲間)の役割は何ですか? 対応するパッケージ内のクラスのリストを見ると、何がニワトリで何がエッグなのか明確ではありません。

私の解釈では、CClass( CPropertyInfoCEnumConstant、 ...) は XSD の最初のドラフト解析で XJC によって作成されます。次に、いくつかの魔法が起こり、このモデルがJClass( JFieldVarJEnumConstant、 ...) に変換され、この変換中にカスタマイズが適用されます。その後、プラグインが呼び出されます。ClassOutlineは、これら 2 つのモデル間のブリッジとして使用されます。全体として非常に複雑に見えます。

これらの並列モデルを使用すると、同じ情報をいくつかの方法で導出できると思います。たとえば、クラス フィールド タイプは次のとおりです。

  • JClass#fields()JFieldVar#typeJType
  • CClassInfo#getProperties()CPropertyInfo#baseTypeJType

上記のモデルのライフサイクルの詳細な説明を探しています。ありがとう。

4

2 に答える 2

20

ああ、ああ、誰かが XJC の内部に興味を持っています。私はおそらく他の誰よりも多くの JAXB プラグインを開発してきたので、何らかの助けになるかもしれません (たとえば、 JAXB2 Basicsを参照してください)。

じゃあ始めよう。XJC では、スキーマ コンパイラはおおよそ次のことを行います。

  • スキーマを解析します
  • スキーマのモデルを作成します (CClass、CPropertyInfo など)。
  • アウトラインを作成します (ClassOutline、FieldOutline など)。
  • コード モデル (JCl​​ass、JDefinedClass、JMethod など) をレンダリングします。
  • 物理コード (ディスク上の Java ファイルなど) を書き込みます。

最後の2つから始めましょう。

Java ファイルについては説明不要だと思います。

コードモデルも比較的簡単です。これは、Java コードをプログラムで構築するために使用できる API です。代わりに文字列連結を使用することもできますが、エラーが発生しやすくなります。CodeModel を使用すると、少なくとも文法的に正しい Java コードを取得できることがほぼ保証されます。ですから、この部分も明確になることを願っています。(ちなみに、私は CodeModel が大好きです。最近、CodeModel のアイデアに基づいてJavaScript コード モデルを作成しました。)

次に、「モデル」と「アウトライン」を見てみましょう。モデルは、受信スキーマを解析した結果です。主に、複合型に対応する「クラス」と、要素、属性、および値に対応する「プロパティ」の観点から、着信スキーマの構造をモデル化します (例: 単純なコンテンツを持つ複合型がある場合)。

モデルは、XML とスキーマに近い論理モデリング構造として理解する必要があります。そのため、それらが持つ型とプロパティを説明するだけです。私がそれをどのように説明しているかは、ワイルドカード型 (xsd:any)、置換グループ、列挙型、組み込み型などから始めて、あらゆる種類の例外と警告があることは確かにはるかに複雑です。

非常に興味深いことに、Modelisの兄弟がRuntimeTypeInfoSetImpl実行時に JAXB によって使用されます。したがって、これはモデルの一種でもありますが、XML スキーマから解析されるのではなく、クラス内の JAXB アノテーションから解析されます。コンセプトは同じです。スーパーコンストラクトであるインターフェースのモデル化とRuntimeTypeInfoSetImpl実装の両方。およびTypeInfoSetのようなインターフェースを確認してください-コンパイル時(およびXJCで)と実行時(JAXB RIの場合など)の両方の実装があります。ClassInfoPropertyInfoCClassInfoCPropertyInfoRuntimeClassInfoImpl

わかりました。XJC がスキーマを解析して分析すると、Model. これModelではまだコードを生成できません。実際、コードを生成するにはさまざまな戦略があります。注釈付きのクラスだけを生成することも、JAXB 1 のようにインターフェース/実装クラスのペアを生成することもできます。コード生成全体は、実際にはモデルのタスクではありません。さらに、Java コードの物理的性質に関連していても、実際にはモデルには関連していない側面が多数あります。たとえば、クラスをパッケージにグループ化する必要があります。これは、モデル自体のプロパティではなく、Java のパッキング システムによって駆動されます。

そして、これがアウトラインの出番です。アウトラインは、スキーマ モデルとコード モデルの間のステップとして見ることができます。JDefinedClassアウトラインは、コードの編成と sからの esの生成を担当するコード モデル要素のファクトリとして表示できますCClassInfo

そうです、それは確かに非常に複雑です。私は Sun/Oracle の従業員ではありません。私はそれを設計しませんでした (私はそれを行った人を知っていますが、彼をとても尊敬しています)。たとえば、特定の設計上の決定についていくつかの理由を推測できます。

  • コンパイル時モデルと実行時モデルに同じインターフェイスを使用する
  • コード生成のさまざまな戦略を許可する
  • プラグインが作成されたモデルを操作できるようにする

この設計が非常に複雑であることには同意しますが、それには理由があります。その証拠の 1 つは、XML から JavaScript へのマッピング用のマッピング ジェネレーターを、基本的に同じモデルで構築することが実際に可能であったことです。スキーマ分析をそのままにして、コード生成を置き換える必要がありました。( Jsonixを参照してください。)

わかりました、うまくいけば、XJC の物事がどのようになっているのかについて、いくつかの光を当てることができれば幸いです。これらの API で頑張ってください。単純ではありません。既存のオープンソース コードを自由に確認してください。多くの例が利用可能です。

ps。本当にずっとこれを書きたかった。:)

于 2012-02-22T22:40:52.110 に答える
2

(これはあなたのさらなる質問に答えるためのものです。)

はい、カスタマイズを確認できます。これは、カスタマイズにアクセスするために使用しているクラスです。

秘訣は、参照プロパティには独自のカスタマイズがなく、カスタマイズは参照される要素のプロパティに配置されることです。

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 は、そのような議論に適した場所だと思います。

于 2012-03-27T23:31:21.977 に答える