2013-05-29 72 views
1

我試圖用MOXY/JAXB 2.5.0實現四人幫的原型模式版本。我希望能夠指定一個項目列表,其中一些是「基於」其他項目,即從其他實例複製數據。對於可重用性,我想創建一個接口,任何能夠實現原型的對象都應該實現這個接口,它將提供註釋以支持該模式所需的屬性。MOXy/JAXB「原型模式」 - 接口繼承

@XmlRootElement(name="IPrototype") 
public interface IPrototype 
{ 
    /** 
    * Acts as a "copy constructor" 
    */ 
    @XmlAttribute(name="prototype") 
    @XmlIDREF 
    public void setPrototype(IPrototype prototype); 

    @XmlAttribute(name="id") 
    @XmlID 
    public void setId(String id); 

    public String getId(); 
} 

的實施對象將理想是這個樣子,甚至沒有與從該接口實現的方法註釋打擾:

@XmlRootElement(name="Item") 
public class Item implements IPrototype 
{ 
    private String m_id = null; 

    private String m_data = null; 

    public Item() 
    { 

    } 

    /** 
    * Never called 
    */ 
    @Override 
    public void setPrototype(IPrototype prototype) 
    { 
     m_data = ((Item)prototype).getData(); 
    } 

    @Override 
    public void setId(String id) 
    { 
     m_id = id; 
    } 

    @Override 
    public String getId() 
    { 
     return m_id; 
    } 

    @XmlAttribute(name="data") 
    public void setData(String data) 
    { 
     m_data = data; 
    } 

    public String getData() 
    { 
     return m_data; 
    } 
} 

和XML看起來像:

<Wrapper> 
    <Item id="Item1" data="stuff and things" /> 
    <Item id="Item2" prototype="Item1" /> 
</Wrapper> 

其中Wrapper定義爲:

@XmlRootElement(name="Wrapper") 
public class Wrapper 
{ 
    @XmlElementRef 
    private ArrayList<Item> m_items = null; 
} 

如果按照我想要的方式工作,我會得到一個包含兩個元素的列表,這兩個元素都包含相同數據的Item類型。然而,MOXy似乎沒有「看到」接口上的註釋,並且我得到了一個沒有設置其XmlID的兩個Items的列表,並且setPrototype()從不被調用。唯一的解決方案似乎是註解Item類中的setPrototype()和setId()方法,但是這似乎需要將setPrototype()的參數類型從IPrototype更改爲Item,因此MOXy將在正確的類中查找XmlID。不幸的是,這打破了繼承的接口。

如果我改爲將列表類型更改爲IPrototype,希望允許MOXy查看其註釋,我會得到相同的行爲 - null ID,setPrototype()永遠不會調用。這實際上並不是我想要的,我希望能夠限制哪些亞型可能包含在特定列表中。

不知道我對接口註釋應該如何工作有正確的期望,也許這是我的錯誤的來源。

有關如何使這項工作的任何想法?在此先感謝,

史蒂夫

更新:如果我註釋Item類,在不改變setPrototype的方法簽名(我想我可以住在一起),我得到的列表,包括兩個項目,以正確設置XmlID的,但setPrototype()仍未調用。看起來像MOXy正在尋找具有相同XmlID而不是Item實例的IPrototype實例(不可能)。

更新2:而且,如果我將IPrototype轉換爲抽象類,那麼一切都很完美。但是,鑑於Java的單一繼承模型,這對於旨在補充多重繼承層次結構的框架對象來說太過於限制。所以仍然卡住。

回答

0

通過註釋Item的屬性和使用泛型聲明setPrototype(),我得到了一個可以接受的版本。這是聲明看起來像在IPrototype:

public <T> void setPrototype(T prototype); 

下面是它的實現在項目:

@XmlAttribute(name="prototype") 
@XmlIDREF 
@Override 
public <T> void setPrototype(T prototype) 
{ 
    m_data = ((Item)prototype).getData(); 
} 

它的工作原理,但我並不特別喜歡不必重新註釋的子類。我已經開了大約一個單獨的問題,因爲它不直觀(我)看起來就是這樣的接口註釋應該工作:

MOXy/JAXB interface annotation

+0

但是,如果我試圖用限制類型參數的申報方法不起作用:公共 void setPrototype(T prototype)。我收到一個異常抱怨說IPrototype沒有用@XmlID註解的屬性。如果我註釋這些方法,那麼setPrototype()不會被調用。現在無界限。 –

0

您可以使用莫西的外部約束力的文件來覆蓋超從Object到接口IPrototype的執行類(即Item)的類。這將允許您繼承接口的映射。

<?xml version="1.0"?> 
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" 
    package-name="forum16807019"> 
    <java-types> 
     <java-type name="Item" super-type="forum16807019.IPrototype"/> 
    </java-types> 
</xml-bindings> 

對於一個完整的示例,請參閱: