2

I'm playing around with JAXB, so a lot of the questions I'm asking are just to see what's possible.

I have the following XML:

<bundleMappings>
    <mapping>
        <parameter attr = "value">asdas</parameter>
        <parameter attr = "value2">d123asdsad</parameter>
        <parameter attr = "value3">0</parameter>
    </mapping>
    <mapping>
        <parameter attr = "value">23123s</parameter>
        <parameter attr = "value2">qwerty</parameter>
        <!-- more parameter elements -->
    </mapping>
    <!-- more mapping elements -->
</bundleMappings>

In which I'd want the parameter elements to be in a Map<String, Parameter> instead of a List, where the key is the attr value and the value is the content of the element. I've followed some blog posts and come up with this.

@XmlRootElement(name = "bundleMmappings")
public class BundleMappings { 
    @XmlElement(name = "mapping")
    private List<Mapping> mMappings;

    //getters setters
}

@XmlAccessorType(XmlAccessType.FIELD) 
public class Mapping {
    @XmlElement
    @XmlJavaTypeAdapter(ParameterAdapter.class)
    private HashMap<String, Parameter> mParameterMap;

    //getters setters
}

@XmlAccessorType(XmlAccessType.FIELD)
public class Parameter {
    @XmlAttribute(name = "attr")
    private String mName;

    @XmlValue
    private String mValue;

    //getters setters
} 

@XmlAccessorType(XmlAccessType.FIELD)
public class Parameters {
    @XmlElement(name = "parameters")
    private List<Parameter> parameters = new LinkedList<>();

    //getters setters
}

And the adapter:

public class ParameterAdapter extends XmlAdapter<Parameters, Map<String, Parameter>> {

    @Override
    public Parameters marshal(Map<String, Parameter> map) throws Exception {
        Parameters params = new Parameters();
        params.setParameters(new ArrayList<Parameter>());
        for (String name : map.keySet()) {
            Parameter p = new Parameter();
            p.setName(name);
            p.setValue(map.get(name).getValue());
            params.getParameters().add(p);
        }
        return params;
    }

    @Override
    public Map<String, Parameter> unmarshal(Parameters value) throws Exception {
        Map<String, Parameter> map = new HashMap<>();
        for (Parameter parameter : value.getParameters()) {
            map.put(parameter.getName(), parameter);
        }
        return map;
    }
}

I did a small unmarshalling test with breakpoints in the Adapter unmarshal and it isn't called at all. Why not?

I also tried annotating the Mapping class List with @XmlElement(name = "parameter"). In this case the unmarshall was called but the Parameters parameter passed to it had an empty list.

Edit

If I try to marshal:

<bundleMappings>
    <mapping>
        <mParameterMap>
            <parameter name="HOME_NETWORK_ID">12345</parameter>
        </mParameterMap>
    </mapping>
</bundleMappings>
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724

1 Answers1

2

When you specify an XmlAdapter on a collection property it applies to the items in the collection.

public class Mapping {
    @XmlElement
    @XmlJavaTypeAdapter(ParameterAdapter.class)
    private List<Parameter> mParameters;

    //getters setters
}

This means ParameterAdapter would need to look something like, where Foo is what you want to convert Parameter to:

public class ParameterAdapter extends XmlAdapter<Foo, Parameter> {

Map Example

Below is a link to an example from my blog where XmlAdapter is used on a Map property:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • @SotiriosDelimanolis - Yes, you had List in your question so I just copied that down to my answer. – bdoughan Jan 07 '13 at 21:35
  • @SotiriosDelimanolis - The XML representation is going to be different from what you are expecting. My suggestion is to create an instance of your object and marshal it to XML and you will see the expected input. – bdoughan Jan 07 '13 at 21:52
  • @SotiriosDelimanolis - Since you are annotating fields make sure you are specifying `@XmlAccessorType(XmlAccessType)` on all your classes: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html – bdoughan Jan 07 '13 at 22:05
  • 1
    @SotiriosDelimanolis - People have too many different naming conventions for fields, if it were the default the `@XmlElement` annotation would need to be used much more. The following link should help with your remaining issue: http://stackoverflow.com/a/13193313/383861 – bdoughan Jan 07 '13 at 22:14
  • I don't want to use more libraries. I gave you the answer because it answers what I needed, but it's just not possible with @XmlElement and @XmlJavaTypeAdapter. I'm just setting my map to @XmlTransient and having a List of Parameter. I'll then have a `getParametersAsMap` method for conversion. – Sotirios Delimanolis Jan 08 '13 at 15:58