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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With