1

我正在尝试使用 MOXy/JAXB 2.5.0 实现四人帮原型模式的一个版本。我希望能够指定一个项目列表,其中一些是“基于”其他的,即从其他实例复制它们的数据。为了可重用性,我想创建一个任何可原型对象都应实现的接口,该接口将为支持该模式所需的属性提供注释。

@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 的项目,并且从未调用 setPrototype()。唯一的解决方案似乎是在 Item 类中注释 setPrototype() 和 setId() 方法,但这似乎需要将 setPrototype() 的参数类型从 IPrototype 更改为 Item,以便 MOXy 将在正确的类中查找 XmlID。不幸的是,这破坏了继承的接口。

如果我改为将列表类型更改为 IPrototype,希望这将允许 MOXy 查看它的注释,我会得到相同的行为 - 空 ID,setPrototype() 从未调用过。无论如何,这并不是我真正想要的,我希望能够限制哪些子类型可能包含在特定列表中。

不确定我对接口注释应该如何工作有正确的期望,也许这就是我错误的根源。

关于如何使它工作的任何想法?提前致谢,

史蒂夫

更新:如果我注释 Item 类,而不更改 setPrototype 的方法签名(我想我可以接受),我会得到一个包含两个项目的列表,正确设置了 XmlID,但仍然没有调用 setPrototype()。似乎 MOXy 正在寻找具有相同 XmlID 的 IPrototype 实例(不可能),而不是 Item 实例。

更新 2:而且,如果我将 IPrototype 转换为抽象类,则一切正常。然而,鉴于 Java 的单继承模型,这对于旨在补充多继承层次结构的框架对象来说过于局限。所以还是卡住了。

4

2 回答 2

0

通过注释 Item 的属性并使用泛型声明 setPrototype(),我得到了一个可以接受的版本。这是 IPrototype 中声明的样子:

public <T> void setPrototype(T prototype);

这是它在 Item 中的实现:

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

它有效,但我并不特别喜欢重新注释子类。我已经就此提出了一个单独的问题,因为它并不直观(对我而言)似乎是界面注释应该工作的方式:

MOXy/JAXB 接口注解

于 2013-06-02T04:37:10.650 回答
0

您可以使用 MOXy 的外部绑定文档将实现类(即Item)的超类覆盖Object到接口IPrototype。这将允许您从接口继承映射。

<?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>

有关完整示例,请参见:

于 2013-06-07T15:08:59.783 回答