2016-12-26 14 views
3

I持って、私は(Digesterの注釈を経由して)ApacheのDigesterのパーサを持つオブジェクトモデルにパースするつもりだ、次のXML文書:ApacheのDigesterのXMLパーサーの注釈および複合モデル

<?xml version="1.0" encoding="UTF-8"?> 
<Decision> 
    <Name>Antivirus software for Windows</Name> 
    <Description>Description 1</Description> 
    <Url>http://yahoo.com</Url> 
    <ImageUrl>http://yahoo.com/img.jpg</ImageUrl> 
    <CriterionGroups> 
     <CriterionGroup> 
      <Name>Windows</Name> 
      <Description>Description 1</Description> 
      <Criteria> 
       <Criterion> 
        <Name>Heuristics</Name> 
        <Description>Description 1</Description> 
       </Criterion> 
      </Criteria> 
     </CriterionGroup> 
    </CriterionGroups> 
    <Criteria> 
     <Criterion> 
      <Name>On-demand scan</Name> 
      <Description>Description 1</Description> 
     </Criterion> 
    </Criteria> 
    <CharacteristicGroups> 
     <CharacteristicGroup> 
      <Name>Windows</Name> 
      <Description>Description 1</Description> 
      <Characteristics> 
       <Characteristic> 
        <Name>Country of origin</Name> 
        <Description>Description 1</Description> 
        <ValueType>String</ValueType> 
        <VisualMode>SelectBox</VisualMode> 
        <Sortable>true</Sortable> 
        <Options> 
         <Option> 
          <Value>Shareware</Value> 
          <Description>Description 1</Description> 
         </Option> 
        </Options> 
       </Characteristic> 
      </Characteristics> 
     </CharacteristicGroup> 
    </CharacteristicGroups> 
    <Characteristics> 
     <Characteristic> 
      <Name>License</Name> 
      <Description>Description 1</Description> 
      <ValueType>Integer</ValueType> 
      <VisualMode>Slider</VisualMode> 
      <Sortable>false</Sortable> 
     </Characteristic> 
    </Characteristics> 
    <Decisions> 
     <Decision> 
      <Name>Avast Free Antivirus</Name> 
      <Description>Description 1</Description> 
      <Url>http://google.com</Url> 
      <ImageUrl>http://google.com/img.jpg</ImageUrl> 
      <Votes> 
       <Vote> 
        <CriterionName>On-demand scan</CriterionName> 
        <Weight>4.3</Weight> 
       </Vote> 
       <Vote> 
        <CriterionName>Heuristics</CriterionName> 
        <CriterionName>On-demand scan</CriterionName> 
        <Weight>4.3</Weight> 
        <Description>Description 1</Description> 
       </Vote> 
      </Votes> 
      <Values> 
       <Value> 
        <CharacteristicName>License</CharacteristicName> 
        <Value>Proprietary</Value> 
        <Description>Description 1</Description> 
       </Value> 
      </Values> 
     </Decision> 
    </Decisions> 
</Decision> 

あなたから見ることができるように

  1. 決定/条件/基準
  2. 決定/ CriterionGroups/CriterionGroup /基準/基準
  3. :このXML 2つの異なるパスにより2つの Criterionノードが存在します

この私のオブジェクトモデル:

@ObjectCreate(pattern = "Decision") 
public class DecisionNode { 

    @BeanPropertySetter(pattern = "Decision/Name") 
    private String name; 
    @BeanPropertySetter(pattern = "Decision/Description") 
    private String description; 
    @BeanPropertySetter(pattern = "Decision/Url") 
    private String url; 
    @BeanPropertySetter(pattern = "Decision/ImageUrl") 
    private String imageUrl; 

    private List<CriterionGroupNode> criterionGroupNodes = new ArrayList<>(); 
    private List<CriterionNode> criterionNodes = new ArrayList<>(); 
    private List<CharacteristicGroupNode> characteristicGroupNodes = new ArrayList<>(); 
    private List<CharacteristicNode> characteristicNodes = new ArrayList<>(); 
    private List<DecisionNode> decisionNodes = new ArrayList<>(); 
    private List<VoteNode> voteNodes = new ArrayList<>(); 
    private List<ValueNode> valueNodes = new ArrayList<>(); 

    .... 

    @SetNext 
    public boolean addCriterionGroupNode(CriterionGroupNode criterionGroupNode) { 
     return criterionGroupNodes.add(criterionGroupNode); 
    } 

    .... 

} 

@ObjectCreate(pattern = "Decision/CriterionGroups/CriterionGroup") 
public class CriterionGroupNode { 

    @BeanPropertySetter(pattern = "Decision/CriterionGroups/CriterionGroup/Name") 
    private String name; 
    @BeanPropertySetter(pattern = "Decision/CriterionGroups/CriterionGroup/Description") 
    private String description; 

    private List<CriterionNode> criterionNodes = new ArrayList<>(); 

    .... 

    @SetNext 
    public boolean addCriterionNode(CriterionNode criterionNode) { 
     return criterionNodes.add(criterionNode); 
    } 

    .... 

} 

@ObjectCreate(pattern = "Decision/Criteria/Criterion") 
public class CriterionNode { 

    @BeanPropertySetter(pattern = "Decision/Criteria/Criterion/Name") 
    private String name; 
    @BeanPropertySetter(pattern = "Decision/Criteria/Criterion/Description") 
    private String description; 

    public CriterionNode() { 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

} 

は、今のところ私はDecision/Criteria/Criterionを解析することができるよしかしNULLはまだDecision/CriterionGroups/CriterionGroup/Criteria/Criterionです。 2つの異なる場所でCriterionNodeを解析できるように、モデルを設定してアノテーションを変更するにはどうすればよいですか?私が見ることができる

enter image description here

答えて

2

2つの問題:まず

、あなたが投稿したコードパーサが代わりに2つのCriterionノードDecision/Criteria/Criterionによって単一のものを見つけ、なぜ

また、私は理解していません決定の直接の子である基準と一致します。つまり、「Decision/CriterionGroups/Criteria/Criteria/Criterion」には一致していますが、「Decision/CriterionGroups/CriterionGroup/Criteria/Criterion」には一致していません。これに対する最も簡単な解決策はただのワイルドカードを使用している:

@ObjectCreate(pattern = "*/Criteria/Criterion") 
public static class CriterionNode { 

    @BeanPropertySetter(pattern = "*/Criteria/Criterion/Name") 
    private String name; 
    @BeanPropertySetter(pattern = "*/Criteria/Criterion/Description") 
    private String description; 

を第二の問題は、CriterionNodeためSetNextのルールであり、そしてこれは少しトリッキーです。本題にするために、私はこのコードをあなたのために働くべきだと思う:

@ObjectCreate(pattern = "Decision") 
public class DecisionNode { 

    ... 

    @SetNext 
    public boolean addCriterionNode(CriterionNode criterionNode) { 
    return criterionNodes.add(criterionNode); 
    } 

} 

@ObjectCreate(pattern = "Decision/CriterionGroups/CriterionGroup") 
public class CriterionGroupNode { 

    ... 

    // no SetNext rule on this method 
    public boolean addCriterionNode(CriterionNode criterionNode) { 
    return criterionNodes.add(criterionNode); 
    } 

} 

この作品の理由は、注釈が設定された次のルールを構築する方法です。

  1. パターン:

    set next ruleは、3つのことを必要とします。

  2. メソッド名。
  3. パラメータタイプ。

それでは、この注釈が達成しようとしていることと等価である:所有DecisionNodeCriterionGroupNodeどちらもどこにでもこのルールに記載されていることを

digester.addSetNext("*/Criteria/Criterion", "addCriterionNode", "CriterionNode") 

注意。

メソッド名とパラメータタイプは簡単です。注釈付きメソッドからまっすぐに来ますが、パターンは明確ではありません。注釈処理では、パラメータに一致する注釈を調べてパターンを推論するので、この場合はパラメータはCriterionNodeであり、「*/Criteria/Criterion」の注釈はObjectCreateと一致しています。

CriterionGroupNodeクラスに2番目のSetNextRuleが必要でない理由は、まったく同じ処理を複製するため、重複したルールが追加されるためです。

Digesterの注釈に

私はDigesterの注釈についてはこれに私の標準免責事項を追加します:個人的に、私は彼らが好き、決して二つの理由のためにそれらを使用しないでください。

  1. ワンより一般的です:私は注釈が使用されるべきだと思うのは、 です。彼らは、クラスの使い方についてではなく、アノテーションの過剰使用に関する私の個人的見解です。
  2. 特にDigesterアノテーションには、非常に単純なケースにしか対応できないだけでなく、これほど簡単なものでも上記のような問題が発生します。

クイックマッピングではルールベースの設定が最も簡単で、拡張が必要な​​場合は最も強力な設定です。この場合は、何かのように: - のgetNameとのsetNameを定義して、あなたのXMLエンティティは、Java Beanが規則に従わないので、BeanPropertySetterRuleの拡張版のみが必要であることを

RulesModule rules = new AbstractRulesModule() { 
    @Override 
    public void configure() { 

    forPattern("Decision") 
     .createObject().ofType(DecisionNode.class); 

    forPattern("Decision/Name").addRule(new BeanPropertySetterRule("name")); 
    forPattern("Decision/Description").addRule(new BeanPropertySetterRule("description")); 
    forPattern("Decision/Url").addRule(new BeanPropertySetterRule("url")); 
    forPattern("Decision/ImageUrl").addRule(new BeanPropertySetterRule("imageUrl")); 

    forPattern("Decision/CriterionGroups/CriterionGroup") 
     .createObject().ofType(CriterionGroupNode.class) 
     .then().setNext("addCriterionGroupNode"); 

    forPattern("Decision/CriterionGroups/CriterionGroup/Name").addRule(new BeanPropertySetterRule("name")); 
    forPattern("Decision/CriterionGroups/CriterionGroup/Description").addRule(new BeanPropertySetterRule("description")); 

    forPattern("*/Criterion") 
     .createObject().ofType(CriterionNode.class) 
     .then().setNext("addCriterionNode"); 

    forPattern("*/Criterion/Name").addRule(new BeanPropertySetterRule("name")); 
    forPattern("*/Criterion/Description").addRule(new BeanPropertySetterRule("description")); 

    } 
}; 

DigesterLoader loader = DigesterLoader.newLoader(rules); 
Digester digester = loader.newDigester(); 

DecisionNode dn = digester.parse(...); 

注(プロパティが低く、ラクダでなければなりませんプロパティ "name"ではなく "Name")。あなたのXMLは、「名前」と「説明」などの小文字のエンティティを使用した場合ので、あなたは使用することができます短い:

forPattern("*/Criterion/Name").setBeanProperty(); 
forPattern("*/Criterion/Description").setBeanProperty(); 

絶対にない理由はありませんJava Beanが規則に従ってください、あなたのXML - 私はこれを指摘しています拡張版がなぜ必要なのか疑問に思った場合。

乾杯

関連する問題