如何使用注释扩展org.simpleframework.xml,该注释将注释写入生成的XML

时间:2012-10-16 13:49:32

标签: java xml serialization simple-framework

我正在使用org.simpleframework.xml(http://simple.sourceforge.net/)将Java对象序列化为XML。

我想补充的是根据Java对象中的Annotations在结果XML中添加注释区域。

所以例如我想写一些Java Object,如:

@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) { ... }

=&GT; OutputNode没有给我机会读取我正在解析的元素的注释。那么应该如何访问属性的注释。

谢谢!

塞巴斯蒂安

1 个答案:

答案 0 :(得分:2)

截至2012-11-05更新:

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-01 20:16更新

这是似乎获得预期效果的解决方法 - 必要的FieldHelper在(Get the value of a field, given the hierarchical path)中描述

    /**
     * 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();
            }
        }
    }

这是我到底有多远。不幸的是,它没有按预期工作。我已经向Simpleframwork for XML的作者写了一封电子邮件。

  /**
  * 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;
}