2017-06-13 3 views
1

Bean階層のプロパティを設定する簡単な方法として、ユニットと統合テストでCommons JXPathを使い始めました。リスト/コレクションのエントリをきれいに設定するためのJXPathの入手方法

JXPathを「きれいに」使用できないシナリオの1つは、リストのエントリを設定することです。

JXPathが「明白なこと」をするのは本当に好きなので、リストのエントリ「[1]」を設定しようとすると(1ベースのインデックスを使用することを選んだのは奇妙です)、少なくとも1つのエントリを持つように基になるリストを構成します。私が見たことから、これは起こらないので、私はそれを手動で行う必要があります。これは、さまざまな理由のカップルのため、動作しません

JXPathContext context = JXPathContext.newContext(request); 
    context.setValue("foo", new Foo()); 
    context.setValue("foo/subscriberNumber", "1234567890"); 
    context.setValue("foo/bar", new Bar()); 
    context.setValue("foo/bar/numbers[1]", "123"); // this fails 

はたとえば、ここに私が書きたいのですがいくつかのコードです。

最初の問題は、 "numbers"リストのプロパティがnullになることです。

JXPathContext context = JXPathContext.newContext(request); 
    context.setValue("foo", new Foo()); 
    context.setValue("foo/subscriberNumber", "1234567890"); 
    context.setValue("foo/bar", new Bar()); 
    context.setValue("foo/bar/numbers", new ArrayList<String>()); 
    context.setValue("foo/bar/numbers[1]", "123"); 

それともAbstractFactoryを登録し、代わりに「createPathAndSetValueを()」を使用できます。私はこのようなことに対処することができます。

ただし、リストが存在する可能性がありますが、サイズがゼロであり、0番目のエントリにアクセスできないため、これは失敗します。

私はこのような何かをすることを強制しています:

JXPathContext context = JXPathContext.newContext(request); 
    context.setValue("foo", new Foo()); 
    context.setValue("foo/subscriberNumber", "1234567890"); 
    context.setValue("foo/bar", new Bar()); 
    context.setValue("foo/bar/numbers", Arrays.asList("")); 
    context.setValue("foo/bar/numbers[1]", "123"); 

私は最初のもの以外にも、リスト内の他のエントリを設定する必要がある場合、私はより多くのダミーエントリを持つリストを初期化する必要があります。

また、私はWTFを鎮圧するためにこれを行うすべての場所にコメントを追加する責任があると感じます。

これを行うクリーナー方法はありますか?

答えて

0

実際、難しいです。まず、

(彼らは1ベースのインデックスを使用することを選んだことを奇数)XPathが機能する方法をです

をdigressing。なぜかの周りにdiscussionsがありますが、私は本当に理由は分かりません。 Luaプログラミング言語は、配列にも1を使用します。

あなたの例に基づいていくつかのコード(GitHubにもあります)があります。 ApacheのコモンズJXPathは、より具体的には、java.util.Listのインスタンスをコレクションを見つけると、それはsetメソッドを呼び出します

public class TestsJxpath { 

    public static class Request { 
     private Foo foo; 
     public Foo getFoo() { 
      return foo; 
     } 
     public void setFoo(Foo foo) { 
      this.foo = foo; 
     } 
     @Override 
     public String toString() { 
      return "Request [foo=" + foo + "]"; 
     } 
    } 

    public static class Foo { 
     private String subscriberNumber; 
     private Bar bar; 
     public String getSubscriberNumber() { 
      return subscriberNumber; 
     } 
     public void setSubscriberNumber(String subscriberNumber) { 
      this.subscriberNumber = subscriberNumber; 
     } 
     public Bar getBar() { 
      return bar; 
     } 
     public void setBar(Bar bar) { 
      this.bar = bar; 
     } 
     @Override 
     public String toString() { 
      return "Foo [subscriberNumber=" + subscriberNumber + ", bar=" + bar + "]"; 
     } 
    } 

    public static class Bar { 
     private List<String> numbers = Arrays.asList(""); 
     public List<String> getNumbers() { 
      return numbers; 
     } 
     @Override 
     public String toString() { 
      return "Bar [numbers=" + numbers + "]"; 
     } 
    } 

    // added after OP reported on 
    // https://stackoverflow.com/questions/44530112/how-to-get-jxpath-to-cleanly-set-list-collection-entries 
    public static void main(String[] args) { 
     Request request = new Request(); 
     JXPathContext context = JXPathContext.newContext(request); 
     context.setValue("foo", new Foo()); 
     context.setValue("foo/subscriberNumber", "1234567890"); 
     context.setValue("foo/bar", new Bar()); 
     context.setValue("foo/bar/numbers[1]", "123"); // this no longer fails 
     System.out.println(request); 
    } 

    public static void main2(String[] args) { 
     Phone p1 = new Phone(1); 
     Phone p2 = new Phone(2); 
     List<Phone> phones = new ArrayList<>(); 
     phones.add(p1); 
     phones.add(p2); 

     JXPathContext ctx = JXPathContext.newContext(phones); 
     System.out.println(phones); 
     long phone1 = (long) ctx.getValue("/*[type='br.eti.kinoshita.commons.jxpath.Phone']"); 
     System.out.println(phone1); 
    } 
} 

。私たちが何を試しても。あなたは工場で、あるいは静的メソッド呼び出しで他のハッキングを試みることもできます....しかし、あなたのケースがあなたのリストに含まれる要素の数を事前に知っていれば、上記のアプローチを使うことができます。つまり

private List<String> numbers = Arrays.asList(""); 

リストを空の要素で初期化すると、List#set(int, E)は例外をスローしません。

希望すると、 ブルーノ

関連する問題