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>
字段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
我自己解决了这个问题。
首先,您需要创建一个 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);
}
实体 "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>
字段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
我自己解决了这个问题。 首先,您需要创建一个 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);
}