xStream中如何指定接口的实现?

How specify realization of interface in xStream?

实体 "messages" 的 XML 描述。

<Message id="11600005" name="some_name">
        <sourcePartitionId>11600</sourcePartitionId>
        <destPartitionId>11700</destPartitionId>
        <payloadId>1300005</payloadId>
        <sourceUdp>1045</sourceUdp>
        <destUdp>1046</destUdp>
        <sourceIp>10.4.48.0</sourceIp>
        <destIp>10.4.49.0</destIp>
        <sourcePort id="1045" name="sp_q_1045_11600_11700_005">
            <type>Queuing</type>
            <maxMessageSize>8192</maxMessageSize>
            <characteristic>1</characteristic>
        </sourcePort>
        <destPort id="1046" name="dp_q_1045_1046_11600_11700_005">
            <type>Queuing</type>
            <maxMessageSize>8192</maxMessageSize>
            <characteristic>1</characteristic>
        </destPort>
    </Message>

字段sourcePortdestPort描述了实现接口ComPort的对象:

public interface ComPort {

    enum PortType {Sampling, Queuing}
    enum PortDirection {Rx,Tx}

    public PortType getPortType();
    public PortDirection getPortDirection();

    public int getMaxMessageSize();
    public int getPortCharacteristic();

接口有两个实现:SamplingPortQueuingPort。两者的主要区别——特征字段。说说如何让xstream基于<type>标签创建对应实现的实例?

重要的一点:还需要考虑的是,当sourcePort标签-方向字段为Tx,而当destPort标记 - 方向字段是 Rx

我自己解决了这个问题。 首先,您需要创建一个 class-Converter:

public class ComPortConverter implements Converter {

    @Override
    public void marshal(Object o, HierarchicalStreamWriter out, MarshallingContext context) {

        ComPort comPort = (ComPort)o;    

        if (comPort.getPortDirection()== ComPort.PortDirection.Tx){
            out.startNode("sourcePort");
        }else {
            out.startNode("destPort");
        }

        out.addAttribute("id",Integer.toString(comPort.getId()));
        out.addAttribute("name", comPort.getName());

        out.startNode("type");
        out.setValue(comPort.getPortType().name());
        out.endNode();

        out.startNode("maxMessageSize");
        out.setValue(Integer.toString(comPort.getMaxMessageSize()));
        out.endNode();

        out.startNode("characteristic");
        out.setValue(Integer.toString(comPort.getPortCharacteristic()));    
        out.endNode();
        out.close();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader in, UnmarshallingContext context) {

        ComPort result;
        ComPort.PortDirection direction=null;

        if (in.getNodeName().equals("sourcePort")){
            direction = ComPort.PortDirection.Tx;
        }else if (in.getNodeName().equals("destPort")){
            direction = ComPort.PortDirection.Rx;
        }
        int id = Integer.parseInt(in.getAttribute("id"));
        String name = in.getAttribute("name");

        in.moveDown();
        if (in.getValue().equals("Sampling")) result = new SamplingPort(id,name);
        else if(in.getValue().equals("Queuing")) result = new QueuingPort(id,name);
        else throw new IllegalArgumentException("Illegal port type value");
        result.setPortDirection(direction);
        in.moveUp();
        in.moveDown();
        result.setMaxMessageSize(Integer.parseInt(in.getValue()));
        in.moveUp();
        in.moveDown();
        result.setPortCharacteristic(Integer.parseInt(in.getValue()));
        in.moveUp();

        return result;
    }

    @Override
    public boolean canConvert(Class type) {
        return ComPort.class.isAssignableFrom(type);
    }
}

然后,您需要注册一个转换器

public static MessagesStorage unmarshallingMessages(File file){
        XStream xStream = new XStream();
        xStream.processAnnotations(new Class[]{MessagesStorage.class,Message.class});
        xStream.registerConverter(new ComPortConverter());
        return (MessagesStorage) xStream.fromXML(file);
    }