Using JAXB 2.0 embedded in JDK 1.6.
Marshal Object to XML bytes:
public byte[] marshalToBytes(Object o) throws Exception { JAXBContext context = JAXBContext.newInstance(o.getClass());
ByteArrayOutputStream bos = new ByteArrayOutputStream(); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); //set XML encoding. m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //output formatted xml. m.setProperty(Marshaller.JAXB_FRAGMENT, false);// ignore XML header or not. m.marshal(o, bos);
return bos.toByteArray(); } |
If you want to output XML to specific file, please udpate "ByteArrayOutputStream bos" to write XML into external file.
Some temporary data or some cycle reference relation.
For example, DDFNode.parentDDFNode.
@XmlJavaTypeAdapter is used to adapter complex Object which is not recognized by JAXB into a simple or customized Object.
1) XmlAdapter.marshal(BoundType):
a. Convert Object to another ValueType which is recognized by JAXB. Or Which is customized rather than JAXB.
b. Used when ObjectàXml
2) XmlAdapter.unmarshal(ValueType):
a. Convert ValueType Object to java Object requested by business logical.
b. Used when XmlàObject
“List<String> tacs” instead of “Set tacs”
@XmlJavaTypeAdapter on field will lead to additional container tag. For example:
@XmlJavaTypeAdapter(FileNamesAdapter.class)
Map<String, String> profileMappings;
Will lead to XML like following:
…
< profileMappings >
<profile-mapping …/>
<!--your wrapper xml element-->;
</ profileMappings >
But not:
<profile-mapping …/>
It’s better to use List<> as collection implementation. And all the Object use simple type.
There should be dedicated Xml Java adapter for DDFNode, because:
1) DFPropterties is dedicated complex element
2) Some elements have empty tag
3) List of child Nodes
4) …
Use field name but not element name.
All the fields should be specified, even some of them are ignored by @XmlTransient.
Normally, JAXB can detect the cycle reference problem.
@XmlSeeAlso({InteriorDDFNode.class, LeafDDFNode.class})
public abstract class DDFNode extends IdClass {
…
}
@XmlSeeAlso can be used to link the bund to its related subclasses. It will be used to define InteriorDDFNode and LeafDDFNode. Because DDFTree use following definition:
@XmlElement(name = "Node") private List<DDFNode> ddfNodes; |
@XmlElementWrapper is used to add a container tag for list,
For model/ddf, model/profile-mapping, there is no @XmlElementWrapper.
But for ddf*.xml, @XmlElementWrapper is used to define container, such as Node/DFProperties/AccessType(Get?, Add?, …).
There is no dedicated DFProperties bean object inside DDFNode.java.
Information for DFProperties are dynamic and has different value types.
Use XmlJavaTypeAdapter convert String value list to AccessType Object List:
List<AccessTypeBase> accessTypes = new ArrayList<AccessTypeBase>(); for (String access : b.accessTypes) { if (access.equalsIgnoreCase(AccessTypeAdd.ACCESS)) { accessTypes.add(new AccessTypeAdd()); } else if (access.equalsIgnoreCase(AccessTypeCopy.ACCESS)) { accessTypes.add(new AccessTypeCopy()); } else if (access.equalsIgnoreCase(AccessTypeDelete.ACCESS)) { accessTypes.add(new AccessTypeDelete()); } else if (access.equalsIgnoreCase(AccessTypeExec.ACCESS)) { accessTypes.add(new AccessTypeExec()); } else if (access.equalsIgnoreCase(AccessTypeReplace.ACCESS)) { accessTypes.add(new AccessTypeReplace()); } else { accessTypes.add(new AccessTypeGet()); } } |
We can also use Map<accessTyeString, classNameString> to ignore many if...else....
Define XmlElements according to different Access Type class instance:
@XmlElementWrapper(name = "AccessType") @XmlElements( { @XmlElement(name="Add",type=AccessTypeAdd.class), @XmlElement(name="Copy",type=AccessTypeCopy.class), @XmlElement(name="Delete",type=AccessTypeDelete.class), @XmlElement(name="Exec",type=AccessTypeExec.class), @XmlElement(name="Get",type=AccessTypeGet.class), @XmlElement(name="Replace",type=AccessTypeReplace.class) }) public List<AccessTypeBase> accessTypes; |
Then it will generate the XML format like following:
<AccessType> <Get/> <Add/> <Replace/> </AccessType> |