2012-08-30 36 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