JaxB Unmarshalling attributes into a hashmap - java

I have the following XML:
<object>
<name>Test</name>
<bikes>
<bike key="Hello" value="World"/>
</bikes>
</object>
So I then have the following Objects:
#XmlRootElement
public class Object {
#XmlElement
private String name;
#XmlElement
private Bikes bikes;
public Object(String name, Bikes bikes) {
this.name = name;
this.bikes = bikes;
}
Bikes
public class Bikes{
private Map<String, String> bike = new HashMap();
#XmlElement
public Bikes(Map<String, String> bike) {
this.bike = bike;
}
I have tried to unmarshall the xml into the the above classes but I am not sure how.
Found a couple of answers on here but none seemed to work as I needed.

You shall be able to do it using adapter class. here is a working case.
Object.java
The class has XmlJavaTypeAdapter(BikeAdapter.class) annoted to bikes map. Adapter and wrapper class are defined here itself.
package testjaxb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Object {
#XmlElement
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getBikes() {
return bikes;
}
public void setBikes(Map<String, String> bikes) {
this.bikes = bikes;
}
#XmlJavaTypeAdapter(BikeAdapter.class)
private Map<String, String> bikes;
public Object() {
}
}
class BikeWrapper {
#XmlElement(name = "bike")
List<Bike> bike = new ArrayList<Bike>();
}
class BikeAdapter extends XmlAdapter<BikeWrapper, Map<String, String>> {
public BikeWrapper marshal(Map<String, String> arg0) throws Exception {
BikeWrapper bw = new BikeWrapper();
List<Bike> bikes = new ArrayList<Bike>();
for (Map.Entry<String, String> entry : arg0.entrySet()) {
bikes.add(new Bike(entry.getKey(), entry.getValue()));
}
bw.bike = bikes;
return bw;
}
public Map<String, String> unmarshal(BikeWrapper arg0) throws Exception {
Map<String, String> r = new HashMap<String, String>();
for (Bike mapelement : arg0.bike) {
r.put(mapelement.getKey(), mapelement.getValue());
}
return r;
}
}
Bike.jaa
package testjaxb;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
#XmlAccessorType(XmlAccessType.FIELD)
public class Bike {
#XmlAttribute()
private String key;
public Bike() {
}
public Bike(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#XmlAttribute()
private String value;
public String toString() {
return "Bike : key-" + getKey() + ", value -" + getValue();
}
}
And here is your Main class to test.
package testjaxb;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class Main {
public static void main(String[] args) throws Exception {
String xmlString = "<object>\n"
+ " <name>Test</name>\n"
+ " <bikes>\n"
+ " <bike key=\"Hello\" value=\"World\"/>\n"
+ " </bikes>\n"
+ "</object>";
testjaxb.Object o = unmarshal(testjaxb.Object.class, xmlString);
System.out.println("Bike List.." + o.getBikes());
}
private static <C> C unmarshal(Class<C> c, String sampleXML) throws Exception {
JAXBContext jc = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader reader = new StringReader(sampleXML);
//System.out.println("" + sampleXML);
return (C) unmarshaller.unmarshal(reader);
}
}

Related

JAXB Annotated Class to Map

I have a class like this
public class Item {
#XmlElement(name = "my_id")
private String id;
#XmlElement(name = "my_type")
private String type;
}
I would like to convert this class to a Map which considers the jaxb annotated fields.
E.g. the Result is a map with following entries:
Key: my_id , Value: "the id"
Key: my_type , Value: "the type"
I am not sure how your xml looks like but assuming, it will be an item element, under some parent, you can do it usingadapter (XmlJavaTypeAdapter) . Sample code looks like below:
package test;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlAccessorType(XmlAccessType.FIELD)
public class Item {
public Item() {
}
#XmlElement(name = "my_id")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#XmlElement(name = "my_type")
private String type;
public String toString() {
return "Item : id-" + getId() + ", type -" + getType();
}
public static void main(String[] args) throws Exception {
String xmlString = "<items>\n"
+ " <item>\n"
+ " <my_id>someID</my_id>\n"
+ " <my_type>someType</my_type>\n"
+ " </item>\n"
+ "</items>";
//System.out.println("xmlString.." + xmlString);
RootElement o = unmarshal(RootElement.class, xmlString);
System.out.println("item Map : "+o.getItem());
}
private static <C> C unmarshal(Class<C> c, String sampleXML) throws Exception {
JAXBContext jc = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader reader = new StringReader(sampleXML);
//System.out.println("" + sampleXML);
return (C) unmarshaller.unmarshal(reader);
}
}
#XmlRootElement(name = "items")
#XmlAccessorType(XmlAccessType.FIELD)
class RootElement {
public RootElement() {
System.out.println("RootElement");
}
public Map<String, String> getItem() {
return item;
}
public void setItem(Map<String, String> item) {
this.item = item;
}
#XmlJavaTypeAdapter(ItemAdapter.class)
#XmlElement()
private Map<String, String> item;
}
class ItemAdapter extends XmlAdapter<Item, Map<String, String>> {
#Override
public Map<String, String> unmarshal(Item i) throws Exception {
Map<String, String> r = new HashMap<String, String>();
r.put("my_id", i.getId());
r.put("my_type", i.getType());
return r;
}
#Override
public Item marshal(Map<String, String> v) throws Exception {
Item i = new Item();
i.setId(v.get("my_id"));
i.setType(v.get("my_type"));
return i;
}
}

Converting XML to Java Object using jaxb (Unmarshal)

I am trying to convert my below xml to java object.
This is my xml:
<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3" xmlns:sdtc="urn:hl7-org:sdtc" xmlns:voc="urn:hl7-org:v3/voc">
<confidentialityCode code="" codeSystem=""/>
<languageCode code="en-"/>
<recordTarget>
<patientRole>
<id root="" extension=""/>
<telecom value="" use=""/>
<providerOrganization>
<id root="" extension=""/>
<id root="" extension=""/>
<name>Something</name>
<telecom value=""/>
<addr use="">
<state></state>
<city></city>
<postalCode></postalCode>
<streetAddressLine>2121</streetAddressLine>
</addr>
</providerOrganization>
</patientRole>
</recordTarget>
</ClinicalDocument>
I need to get the value of "name" under "providerOrganization".
Below are my Java classes.
ClinicalDocument.java
package com.biclinical.data;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="ClinicalDocument", namespace="urn:hl7-org:v3")
public class ClinicalDocument {
#XmlElement(name="recordTarget")
private List<RecordTarget> recordTarget;
public List<RecordTarget> getRecordTarget() {
return recordTarget;
}
public void setRecordTarget(List<RecordTarget> recordTarget) {
this.recordTarget = recordTarget;
}
#Override
public String toString() {
return "ClinicalDocument [recordTarget=" + recordTarget + "]";
}
}
RecordTarget.java
package com.biclinical.data;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="recordTarget")
public class RecordTarget {
#XmlElement(name="patientRole")
private List<PatientRole> patientRole;
public List<PatientRole> getPatientRole() {
return patientRole;
}
public void setPatientRole(List<PatientRole> patientRole) {
this.patientRole = patientRole;
}
#Override
public String toString() {
return "RecordTarget [patientRole=" + patientRole +"]";
}
}
PatientRole.java
package com.biclinical.data;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "patientRole")
public class PatientRole {
/*#XmlElement(name = "id")
private String id;
Double root;
String extension;*/
#XmlElement(name="providerOrganization")
private List<ProviderOrganization> providerOrganization;
public List<ProviderOrganization> getProviderOrganization() {
return providerOrganization;
}
public void setProviderOrganization(List<ProviderOrganization> providerOrganization) {
this.providerOrganization = providerOrganization;
}
}
ProviderOrganisation.java
package com.biclinical.data;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="providerOrganization")
public class ProviderOrganization {
#XmlElement(name="name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Patient [Name=" + name + "]";
}
}
XMLFileParserSAXUtility.java
public class XMLFileParserSAXUtility extends DefaultHandler {
public static void main(String[] args) {
try {
File file = new File("C:/Users/shivendras/Desktop/Patient19999_Test_Organization1.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] {ClinicalDocument.class,RecordTarget.class,PatientRole.class,ProviderOrganization.class});
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ClinicalDocument clinicalDocument = (ClinicalDocument) jaxbUnmarshaller.unmarshal(file);
//clinicalDocument.getRecordTarget()
String s = ((File) ((PatientRole) ((RecordTarget) clinicalDocument.getRecordTarget()).getPatientRole()).getProviderOrganization()).getName();
System.out.println(s);
} catch (JAXBException e) {
e.printStackTrace();
}
}
I get the result as
Exception in thread "main" java.lang.NullPointerException
at com.biclinical.util.XMLFileParserSAXUtility.main(XMLFileParserSAXUtility.java:27)
And if i try to print syso(clinicalDocument);
Result is ClinicalDocument [recordTarget=null]
Please help me out here!
I think you add the namespace to your #XmlElement :
#XmlElement(name="patientRole")
private List<PatientRole> patientRole;
Should be :
#XmlElement(name="patientRole",namespace="urn:hl7-org:v3")
private List<PatientRole> patientRole;
If you're having any other null in your objects, try adding the namespace.
Also, #XmlRootEntity is only necessary for your root element, in this case your ClinicalDocumentclass, and you only need to give the root class to your JAXBContext :
JAXBContext jaxbContext = JAXBContext.newInstance(ClinicalDocument.class);

com.google.gson.JsonSyntaxException:Expected STRING but was BEGIN_ARRAY

Kindly help me to get the subnodes list inside bom attributes
JSON file
[
{
"subConfigId":"bac",
"totalPrice":"634.00",
"bom":{
"ucid":"ucid",
"type":"RootNode",
"attributes":{
"visible":true,
"price_status":"SUCCESS"
},
"subnodes":[
{
"description":"Enterprise Shock Rack",
"ucid":"ucid"
},
{
"description":"SVC",
"ucid":"ucid"
}
]
},
"breakdown":{
"SV":550.0,
"HW":6084.0
},
"currency":"USD"
}
]
GsonNodes.java
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class GsonNodes {
public static void main(String[] args) throws IOException {
try{
JsonElement je = new JsonParser().parse(new FileReader(
"C:/Desktop/json.txt"));
JsonArray ja = je.getAsJsonArray();
Iterator itr = ja.iterator();
while(itr.hasNext()){
JsonElement je1 = (JsonElement) itr.next();
Gson gson = new Gson();
Details details = gson.fromJson(je1, Details.class);
System.out.println(details.getSubConfigId());
System.out.println(details.getCurrency());
System.out.println(details.getBreakdown());
System.out.println(details.getTotalPrice());
System.out.println(details.getBom().getUcid());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Details.java POJO
import java.io.Serializable;
import java.util.Map;
public class Details implements Serializable{
private String subConfigId;
private String totalPrice;
private Bom bom;
private String currency;
private Map<String, String> breakdown;
public String getSubConfigId() {
return subConfigId;
}
public void setSubConfigId(String subConfigId) {
this.subConfigId = subConfigId;
}
public String getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(String totalPrice) {
this.totalPrice = totalPrice;
}
public Bom getBom() {
return bom;
}
public void setBom(Bom bom) {
this.bom = bom;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public Map<String, String> getBreakdown() {
return breakdown;
}
public void setBreakdown(Map<String, String> breakdown) {
this.breakdown = breakdown;
}
}
Bom.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Bom implements Serializable{
private String ucid;
private String type;
private Map<String, String> attributes;
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
public String getUcid() {
return ucid;
}
public void setUcid(String ucid) {
this.ucid = ucid;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
#Override
public String toString(){
return getUcid() + ", "+getType()+", "+getAttributes();
}
}
Subnodes.java
import java.io.Serializable;
import java.util.Map;
public class Subnodes implements Serializable{
private String description;
private String ucid;
private Map<String, String> attributes;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUcid() {
return ucid;
}
public void setUcid(String ucid) {
this.ucid = ucid;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
}
I am getting an error , when i try to get the "subnodes"
I added the following code in the class
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
then i am getting the error "Expected STRING but was BEGIN_ARRAY"
kindly help me that how can i get the "subnodes" list
In Bom.java
Please add a getter/setter method for :
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
public List<Subnodes> getSubnodes() {
return subnodes;
}
public void setSubnodes(List<Subnodes> subnodes) {
this.subnodes = subnodes;
}
i have tried as below .. this is working fine.
package com.brp.mvc.util;
import java.io.IOException;
import java.util.Iterator;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class GsonNodes {
public static void main(String[] args) throws IOException {
try {
JsonElement je = new JsonParser().parse("[{\"subConfigId\":\"bac\",\"totalPrice\":\"634.00\",\"bom\":{\"ucid\":\"ucid\",\"type\":\"RootNode\",\"attributes\":{\"visible\":true,\"price_status\":\"SUCCESS\"},\"subnodes\":[{\"description\":\"Enterprise Shock Rack\",\"ucid\":\"ucid\"},{\"description\":\"SVC\",\"ucid\":\"ucid\"}]},\"breakdown\":{\"SV\":550.0,\"HW\":6084.0},\"currency\":\"USD\"}]");
JsonArray ja = je.getAsJsonArray();
Iterator itr = ja.iterator();
while (itr.hasNext()) {
JsonElement je1 = (JsonElement) itr.next();
Gson gson = new Gson();
Details details = gson.fromJson(je1, Details.class);
System.out.println(details.getSubConfigId());
System.out.println(details.getCurrency());
System.out.println(details.getBreakdown());
System.out.println(details.getTotalPrice());
System.out.println(details.getBom().getUcid());
System.out.println(details.getBom().getSubnodes().get(0).getDescription());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
i have added one method to convert json into string as below :
public static String readFile(String filename) {
String result = "";
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
line = br.readLine();
}
result = sb.toString();
} catch(Exception e) {
e.printStackTrace();
}
return result;
}
and use this method like below :
JsonElement je = new JsonParser().parse(readFile("C:/Desktop/json.txt"));

JAXB - How to create the XML element with attributes from Map?

I need something like this -
<Token>
<HighLevel info-1="" info-2=""/>
<LowLevel>
<LowLevel info-key="" info-value=""/>
<LowLevel info-key="" info-value=""/>
....
</LowLevel>
</Token >
I've the Map for LowLevel element, whose entries I want to populate like above XML.
What could be the way to encapsulate/bind this using JAXB?
You could use a custom adapter for this. Example
//Token.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
class LowLevelToken {
#XmlAttribute(name = "info-key")
public String key;
#XmlAttribute(name = "info-value")
public String value;
private LowLevelToken() {}
public LowLevelToken(String key, String value) {
this.key = key;
this.value = value;
}
}
#XmlRootElement
class HighLevelToken {
#XmlAttribute(name = "info-1")
public String info1;
#XmlAttribute(name = "info-2")
public String info2;
private HighLevelToken() {}
public HighLevelToken(String info1, String info2) {
this.info1 = info1;
this.info2 = info2;
}
}
class TokenWrapper {
#XmlElement(name="LowLevel")
public List<LowLevelToken> tokens = new ArrayList<LowLevelToken>();
}
class TokenAdapter extends XmlAdapter<TokenWrapper, Map<String, String>> {
#Override
public TokenWrapper marshal(Map<String, String> lowlevelTokens)
throws Exception {
TokenWrapper wrapper = new TokenWrapper();
List<LowLevelToken> elements = new ArrayList<LowLevelToken>();
for (Map.Entry<String, String> property : lowlevelTokens.entrySet()) {
elements.add(new LowLevelToken(property.getKey(), property.getValue()));
}
wrapper.tokens = elements;
return wrapper;
}
#Override
public Map<String, String> unmarshal(TokenWrapper tokenWrapper) throws Exception {
Map<String, String> tokens = null;
if(tokenWrapper != null && tokenWrapper.tokens != null && !tokenWrapper.tokens.isEmpty()){
tokens = new HashMap<String, String>();
for(LowLevelToken token : tokenWrapper.tokens){
tokens.put(token.key, token.value);
}
}
return tokens;
}
}
#XmlRootElement(name = "Token")
public class Token {
HighLevelToken highLevel;
Map<String, String> lowLevel;
public HighLevelToken getHighLevel() {
return highLevel;
}
#XmlElement(name = "HighLevel")
public void setHighLevel(HighLevelToken highLevel) {
this.highLevel = highLevel;
}
public Map<String, String> getLowLevel() {
return lowLevel;
}
#XmlElement(name = "LowLevel")
#XmlJavaTypeAdapter(TokenAdapter.class)
public void setLowLevel(Map<String, String> lowLevel) {
this.lowLevel = lowLevel;
}
}
A sample program
import java.util.HashMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class JAXBExample {
public static void main(String[] args) {
Token token = new Token();
token.setHighLevel(new HighLevelToken("1", "2"));
token.setLowLevel(new HashMap<String, String>() {{ put("LK1", "LV1"); put("LK2", "LV2"); put("LK2", "LV2"); }});
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Token.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(token, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
This generates
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Token>
<HighLevel info-1="1" info-2="2"/>
<LowLevel>
<LowLevel info-key="LK2" info-value="LV2"/>
<LowLevel info-key="LK1" info-value="LV1"/>
</LowLevel>
</Token>

Java/JAXB: Unmarshall XML attributes to specific Java object attributes

There's ugly XML file that has to be unmarshalled:
<?xml version="1.0" ?>
<configuration>
<section name="default_options">
<value name="default_port">8081</value>
<value name="log_level">WARNING</value>
</section>
<section name="custom_options">
<value name="memory">64M</value>
<value name="compatibility">yes</value>
</section>
</configuration>
Resulting Java Objects should be:
public class DefaultOptions {
private int defaultPort;
private String logLevel;
// etc...
}
public class CustomOptions {
private String memory;
private String compatibility;
// etc...
}
This question's answer is very close but I can't figure out the final solution.
How about?
Introduce a common super class called Options:
import javax.xml.bind.annotation.XmlAttribute;
public abstract class Options {
private String name;
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Then on your class with the list of options (Configuration in this example), specify an #XmlJavaTypeAdapter on that property:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Configuration {
private List<Options> section = new ArrayList<Options>();
#XmlJavaTypeAdapter(OptionsAdapter.class)
public List<Options> getSection() {
return section;
}
public void setSection(List<Options> section) {
this.section = section;
}
}
The XmlAdapter will look something like this:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class OptionsAdapter extends XmlAdapter<AdaptedOptions, Options> {
#Override
public Options unmarshal(AdaptedOptions v) throws Exception {
if("default_options".equals(v.name)) {
DefaultOptions options = new DefaultOptions();
options.setName(v.getName());
options.setDefaultPort(Integer.valueOf(v.map.get("default_port")));
options.setLogLevel(v.map.get("log_level"));
return options;
} else {
CustomOptions options = new CustomOptions();
options.setName(v.getName());
options.setCompatibility(v.map.get("compatibility"));
options.setMemory(v.map.get("memory"));
return options;
}
}
#Override
public AdaptedOptions marshal(Options v) throws Exception {
AdaptedOptions adaptedOptions = new AdaptedOptions();
adaptedOptions.setName(v.getName());
if(DefaultOptions.class == v.getClass()) {
DefaultOptions options = (DefaultOptions) v;
adaptedOptions.map.put("default_port", String.valueOf(options.getDefaultPort()));
adaptedOptions.map.put("log_level", options.getLogLevel());
} else {
CustomOptions options = (CustomOptions) v;
adaptedOptions.map.put("compatibility", options.getCompatibility());
adaptedOptions.map.put("memory", options.getMemory());
}
return adaptedOptions;
}
}
AdaptedOptions looks like:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlValue;
public class AdaptedOptions extends Options {
#XmlAttribute String name;
#XmlElement List<Value> value = new ArrayList<Value>();
Map<String, String> map = new HashMap<String, String>();
public void beforeMarshal(Marshaller marshaller) {
for(Entry<String, String> entry : map.entrySet()) {
Value aValue = new Value();
aValue.name = entry.getKey();
aValue.value = entry.getValue();
value.add(aValue);
}
}
public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
for(Value aValue : value) {
map.put(aValue.name, aValue.value);
}
}
private static class Value {
#XmlAttribute String name;
#XmlValue String value;
}
}
You may create a separate classes to represent structure of your XML:
public class Section {
#XmlAttribute
public String name;
#XmlElement(name = "value")
public List<Value> values;
}
public class Value {
#XmlAttribute
public String name;
#XmlValue
public String value;
}
and then use an XmlAdapter to perform conversion:
public class OptionsAdapter extends XmlAdapter<Section, Options> {
public Options unmarshal(Section s) {
if ("default_options".equals(s.name)) {
...
} else if (...) {
...
}
...
}
...
}
#XmlElement
public class Configuration {
#XmlElement(name = "section")
#XmlJavaTypeAdapter(OptionsAdapter.class)
public List<Options> options;
}
public class DefaultOptions extends Options { ... }
public class CustomOptions extends Options { ... }

Categories