MOXy / JAXB“原型模式” - 接口继承 [英] MOXy/JAXB "prototype pattern" - interface inheritance

查看:128
本文介绍了MOXy / JAXB“原型模式” - 接口继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement a version of Gang of Four's Prototype Pattern using MOXy/JAXB 2.5.0. I want to be able to specify a list of items, some of which are "based on" others, i.e. copy their data from other instances. For reusability, I'd like to create an interface that any prototype-able object should implement, which will provide annotation for the properties necessary to support the pattern.

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

理想情况下,实现对象看起来像这样,甚至不必费心从接口实现的方法的注释:

An implementing object would ideally look something like this, not even having to bother with annotation of the methods implemented from the interface:

@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定义为:

where Wrapper is defined as:

@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。不幸的是,这打破了继承的接口。

If it worked the way I want, I would get a list with two elements, both of type Item, that contain the same data. However, MOXy doesn't seem to "see" the annotations on the interface, and I get a list with two Items that don't have their XmlID set, and setPrototype() is never called. The only solution appears to be annotating the setPrototype() and setId() methods in the Item class, but this appears to require changing setPrototype()'s argument type from IPrototype to Item so MOXy will look for the XmlID in the right class. Unfortunately, this breaks the inherited interface.

如果我改为将列表类型更改为IPrototype,希望MOXy能够看到它的注释,我会得到相同的行为 - null ID,setPrototype()永远不会被调用。这不是我想要的,我希望能够限制特定列表中可能包含哪些子类型。

If I instead change the list type to IPrototype, hoping that would allow MOXy to see its annotations, I get the same behavior - null ID's, setPrototype() never called. This isn't really what I want anyways, I'd like to be able to constrain which subtypes may be included in a particular list.

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

Not sure I have correct expectations for how interface annotations are supposed to work, maybe that's the source of my error.

有关如何使其工作的任何想法?在此先感谢,

Any thoughts on how to get this working? Thanks in advance,

史蒂夫

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

UPDATE: If I annotate the Item class, WITHOUT changing setPrototype's method signature (which I guess I can live with), I get a list with two items, with correctly set XmlID's, but setPrototype() is still not called. Seems like MOXy is looking for instances of IPrototype (impossible) with the same XmlID, not Item instances.

更新2:并且,如果我将IPrototype转换为抽象类,一切都很完美。但是,考虑到Java的单继承模型,这对于旨在补充多个继承层次结构的框架对象来说太有限了。所以仍然坚持。

UPDATE 2: And, if I convert IPrototype into an abstract class, everything works perfectly. However, given Java's single inheritance model, this is too limiting for a framework object that is intended to supplement multiple inheritance hierarchies. So still stuck.

推荐答案

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

I got a somewhat acceptable version of this running by annotating Item's properties and declaring setPrototype() using generics. This is what the declaration looks like in IPrototype:

public <T> void setPrototype(T prototype);

这是它在Item中的实现:

And here's its implementation in Item:

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

它有效,但我不特别喜欢重新注释子类。我已经打开了一个单独的问题,因为它不直观地(对我来说)看起来就像界面注释应该起作用的方式:

It works, but I don't particularly like having to re-annotate the subclass. I've opened a separate question about that, since it doesn't intuitively (to me) seem like that's the way interface annotations should work:

MOXy/JAXB界面注释

这篇关于MOXy / JAXB“原型模式” - 接口继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆