Ashok
Ashok

Reputation: 21

Create objects inside JAXB generation

I have an xml like below one.

<price>
  <priceCalculator ie="carID" renderer = "com.a.carCalculator"> 
      <argument name="param1" value="paramValue"/>
      .....
  </priceCalculator>
  <priceCalculator id="TVS" renderer = "com.a.TwoWheelerCalculator">
     <argument name="param1" value="paramValue"/>
     .....
  </priceCalculator>
</price>

When the JAXB is parsed, I want to have the renderer class object to be created attached with priceCalculator object. For example, priceCalculator.getRenderrer() should return the CarCalculator or TwoWheelerCalculator object based on attribute value. We can assume that the calculator class has default constructor.

How can I achieve this? Please help.

Upvotes: 2

Views: 240

Answers (2)

bdoughan
bdoughan

Reputation: 148977

You could use an XmlAdapter for this use case:

ClassAdapter

The XmlAdpater will convert the object to its class name during a marshal, and instantiate an instance of the specified class on an unmarshal.

package forum9444545;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class ClassAdapter extends XmlAdapter<String, Object>{

    @Override
    public String marshal(Object object) throws Exception {
        if(null == object) {
            return null;
        }
        return object.getClass().getName();
    }

    @Override
    public Object unmarshal(String string) throws Exception {
        if(null == string) {
            return null;
        }
        return Thread.currentThread().getContextClassLoader().loadClass(string).newInstance();
    }

}

PriceCalculator

The @XmlJavaTypeAdapter annotation is used to register the XmlAdapter on the appropriate field/property:

package forum9444545;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlAccessorType(XmlAccessType.FIELD)
public class PriceCalculator {

    @XmlAttribute
    private String id;

    @XmlAttribute
    @XmlJavaTypeAdapter(ClassAdapter.class)
    private Object renderer;

}

For More Information on XmlAdapter

Upvotes: 0

Russell Zahniser
Russell Zahniser

Reputation: 16354

Fo something tricky like this, I would use the Java-to-XML schema mapping mode, and I would have the JAXB class just be a builder of the "real" class. Then you can control exactly how it is unmarshalled:

class PriceCalculator {
    Calculator renderer;

    PriceCalculator(Builder builder) {
        Class<?> calculatorClass = Class.forName(builder.renderer);
        renderer = (Calculator)calculatorClass.newInstance();
    }

    @XmlType(name="PriceCalculator")
    static class Builder {
        @XmlAttribute
        String renderer;
    }
}

Upvotes: 1

Related Questions