3

org.simpleframework.xml(http://simple.sourceforge.net/)を使用してJavaオブジェクトをXMLにシリアル化します。

追加したいのは、Javaオブジェクトの注釈に基づいて、結果のXMLにコメント領域を追加することです。

たとえば、次のようなJavaオブジェクトを記述したいと思います。

@Root(name = "myclass")
public class MyClass {
  @Element(required=true)
  @Version(revision=1.1)
  @Comment(text=This Element is new since, version 1.1, it is a MD5 encrypted value)
  private String activateHash;
}

結果のxmlは次のようになります。

<myclass version="1.1">
  <!-- This Element is new since, version 1.1, it is a MD5 encrypted value -->
  <activateHash>129831923131s3jjs3s3jjk93jk1</activateHash>
</myclass>

xmlにコメントを書き込む訪問者の書き方に関する例がドキュメントにあります: http ://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#intercept

ただし、どうすれば訪問者を戦略に結び付けることができますか?

さらに、simpleframeworkのVisitorの概念では、生の解析クラスにアクセスできません。ビジターには、上書きする方法しかありません。

public void write(Type type, NodeMap<OutputNode> node) { ... }

=> OutputNodeは、解析している要素の注釈を読み取る機会を与えてくれません。では、属性のアノテーションにどのようにアクセスする必要がありますか。

ありがとう!

セバスチャン

4

1 に答える 1

2

2012年11月5日現在の更新:

org.simpleframework.xmlの作者による回答:これは機能します

https://simple.svn.sourceforge.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/strategy/CommentTest.java

package org.simpleframework.xml.strategy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.simpleframework.xml.Default;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.ValidationTestCase;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.NodeMap;
import org.simpleframework.xml.stream.OutputNode;

public class CommentTest extends ValidationTestCase {

   @Retention(RetentionPolicy.RUNTIME)
   private static @interface Comment {
      public String value();
   }

   @Root
   @Default
   private static class CommentExample {
      @Comment("This represents the name value")
      private String name;
      @Comment("This is a value to be used")
      private String value;
      @Comment("Yet another comment")
      private Double price;
   }

   private static class CommentVisitor implements Visitor {
      public void read(Type type, NodeMap<InputNode> node) throws Exception {}
      public void write(Type type, NodeMap<OutputNode> node) throws Exception {
         if(!node.getNode().isRoot()) {
            Comment comment = type.getAnnotation(Comment.class);
            if(comment != null) {
               node.getNode().setComment(comment.value());
            }
         }
      }
   }

   public void testComment() throws Exception {
      Visitor visitor = new CommentVisitor();
      Strategy strategy = new VisitorStrategy(visitor);
      Persister persister = new Persister(strategy);
      CommentExample example = new CommentExample();

      example.name = "Some Name";
      example.value = "A value to use";
      example.price = 9.99;

      persister.write(example, System.out);
   }

}

2012-11-0120:16現在の更新

これは、目的の効果が得られると思われる回避策です。必要なFieldHelperについては、(階層パスを指定してフィールドの値を取得する)で説明されています。

    /**
     * write according to this visitor
     */
    public void write(Type type, NodeMap<OutputNode> node) {
        OutputNode element = node.getNode();
        Class ctype = type.getType();

        String comment = ctype.getName();
        if (!element.isRoot()) {
            FieldHelper fh = new FieldHelper();
            element.setComment(comment);
            try {
                if (type.getClass().getSimpleName().startsWith("Override")) {
                    type = (Type) fh.getFieldValue(type, "type");
                }
                if (type.getClass().getSimpleName().startsWith("Field")) {
                    Field field = (Field) fh.getFieldValue(type, "field");
                    System.out.println(field.getName());
                    Comment commentAnnotation = field.getAnnotation(Comment.class);
                    if (commentAnnotation != null) {
                        element.setComment(commentAnnotation.value());
                    }
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

これが私がこれでどこまで到達したかです。残念ながら、期待どおりに機能しません。SimpleframworkforXMLの作者にメールを書きました。

  /**
  * write according to this visitor
  */
    public void write(Type type, NodeMap<OutputNode> node) {
        OutputNode element = node.getNode();
        Class ctype = type.getType();

        String comment = ctype.getName();
        if (!element.isRoot()) {
            Comment commentAnnotation = type.getAnnotation(Comment.class);
            if (commentAnnotation!=null)
                element.setComment(commentAnnotation.value());
            else
                element.setComment(comment);
        }
    }

    @Override
    public void read(Type type, NodeMap<InputNode> nodeMap) throws Exception {

    }

}

コメントアノテーションを次のように宣言しました。

package com.bitplan.storage.simplexml;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment {
String value();
}

これは次のように使用できます。

@Comment("this is the unique identifier")
private long id;

ビジターの追加は次のように可能でした:

/**
 * get Serializer
 * 
 * @return
 */
public Serializer getSerializer() {
    Serializer serializer = null;
    Strategy strategy=null;
    VisitorStrategy vstrategy=null;
    if ((idname != null) && (refname != null)) {
        strategy = new CycleStrategy(idname, refname);
    }
    CommentVisitor cv=new CommentVisitor();
    if (strategy==null) {
        vstrategy=new VisitorStrategy(cv);
    } else {
        vstrategy=new VisitorStrategy(cv,strategy);
    }       
    serializer = new Persister(vstrategy);
    return serializer;
}
于 2012-11-02T16:54:36.800 に答える