2016-07-19 3 views
2

XML-описание сущностей «сообщения».Как определить реализацию интерфейса в xStream?

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

В полях sourcePort и destPort описал объект, который реализует интерфейс ComPort:

public interface ComPort { 

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

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

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

В интерфейсе есть две реализации: SamplingPort и QueuingPort. И основное отличие - характеристическое поле. Скажите мне, как сделать xstream на основе тега <type>, создает экземпляр соответствующей реализации?

Важно: Также необходимо учитывать, что при sourcePort тег - направление поля Tx, а когда destPort тег - направление поля Rx

ответ

0

я понял, этот вопрос сам. Во-первых, вам нужно создать класс-конвертер:

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