2012-08-30 34 views
1

我有一个相当复杂的数据结构,我似乎无法正确取消编组。JAXB XmlIDREF和地图/列表

@XmlRootElement 
class Tree { 
    @XmlID 
    private String id; 

    @XmlJavaTypeAdapter(type=TreeFooAdapter.class) 
    Map<Tree, Foo> fooMap; 
} 

class Foo { 
    @XmlID 
    private String id; 
} 

我有两个独立的树。两个节点(每棵树一个)可以配对并与Foo的一个实例关联。 fooMap用于跟踪给定树节点已配对的其他节点以及Foo结果的实例。

的TreeFooAdapter是非常简单的,但要注意,它使用ID裁判:

public class TreeFooAdapter extends XmlAdapter<TreeFooAdapter.MapType, Map<Tree, Foo>> { 
    public static class MapType { 
    public static class MapEntry { 
     @XmlAttribute 
     @XmlIDREF 
     public Tree key; 
     @XmlAttribute 
     @XmlIDREF 
     public Foo value; 
    } 
    // etc... 
    } 

    // Standard drill for marshal/unmarshal... 
} 

的问题:正向引用不工作!解组时,无论哪个Tree在XML中首先出现,都会在其fooMap中具有空键。由于这两棵树相互引用,所以我无法改变XML的顺序来解决这个问题。

我试过了一个黑客,其中我有一个私人方法来获取/设置List<TreeFooMapEntry>,但它会产生相同的结果。

为什么JAXB在包含在Map或List中时无法处理转发ID引用,以及如何解决这个问题?

回答

0

我发现了一个(可怕的,可怕的,丑陋的)解决方法,灵感来自this。我基本上推广了PhoneNumberAdapter类来处理任何“可识别的”,即具有唯一的ID(即,Foo和树)。而不是有一个AdaptedPhoneNumber类,我有一个ObjectWrapper bean,它将包含被包装的实际对象(当第一次遇到时),或者只包含它的ID(在后续遇到时)。 TreeFooAdapter中的MapEntry类不是具有XmlIDREFs,而是将我的IdentifiableAdapter指定为XmlJavaTypeAdapter。

这会造成糟糕透顶的XML,但至少可以工作。不过,这看起来像是JAXB中的一个错误:经过一些痛苦的调试之后,我仍然无法弄清楚为什么XmlIDREF在适配的Map类中不起作用。

+0

...虽然在为我的单元测试添加更多深度之后,我发现这不起作用,无论是... :( – Kricket

0

我尝试了另一个似乎在这次工作的黑客。诀窍涉及以下内容:

  • 创建一个私有的getter/setter对,转化成fooMap TreeFooAdapter.MapType
  • 的XmlID添加到TreeFooAdapter.MapType,并与XmlIDREF注释吸气
  • 保持静止集的TreeFooAdapter.MapType的实例
  • 编组时,编组所有实例的树和Foo之后,也编组实例。

这将产生更清洁的XML:树被他们fooMaps IDREF的简单整理和XML文件的末尾是TreeFooAdapter.MapTypes,其本身只是IDREF的对的列表只是一个长长的清单。如果您不止一次编组/解组,请务必清理静态Set实例。

+0

它也使fooMap的重复,出于某种原因... – Kricket