dnet-core/dnet-core-components/src/main/java/eu/dnetlib/miscutils/jaxb/JaxbFactory.java

217 lines
5.1 KiB
Java

package eu.dnetlib.miscutils.jaxb;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
/**
* Common base class for implementing the Jaxb ObjectFactory pattern.
*
* @author marko
*
* @param <T>
* type of the roote element
*/
@XmlRegistry
public class JaxbFactory<T> {
/**
* jaxb context.
*/
private JAXBContext context;
/**
* class for the root element handled by this factory.
*/
private Class<T> clazz;
/**
* Prevent instantiating with 0 arguments.
*
* @throws JAXBException
*/
protected JaxbFactory() throws JAXBException {
// prevent instantiation
}
/**
* creates a new jaxb factory.
*
* This constructor is needed because spring constructor injection doesn't work well will varargs.
*
* @param clazz
* @throws JAXBException
*/
public JaxbFactory(final Class<? extends T> clazz) throws JAXBException {
this(clazz, new Class<?>[] {});
}
/**
* creates a new jaxb factory.
*
* @param clazz
* class for the root element
* @param classes
* other classes
* @throws JAXBException
* could happen
*/
@SuppressWarnings("unchecked")
public JaxbFactory(final Class<? extends T> clazz, Class<?>... classes) throws JAXBException {
Class<?>[] all = new Class<?>[classes.length + 1];
for (int i = 0; i < classes.length; i++)
all[i + 1] = classes[i];
all[0] = clazz;
this.clazz = (Class<T>) clazz;
context = JAXBContext.newInstance(all);
}
/**
* Create a new T instance.
*
* @return new T instance
*/
public T newInstance() {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("jaxb bean not instantiable, e");
} catch (IllegalAccessException e) {
throw new IllegalStateException("jaxb bean not instantiable, e");
}
}
/**
* Parses a given string and creates a java object.
*
* @param value
* serialized representation
* @return java object
* @throws JAXBException
* could happen
*/
public T parse(final String value) throws JAXBException {
return parse(new StreamSource(new StringReader(value)));
}
/**
* Parses a given source and creates a java object.
*
* @param source
* serialized representation
* @return java object
* @throws JAXBException
* could happen
*/
@SuppressWarnings("unchecked")
public T parse(final Source source) throws JAXBException {
final Unmarshaller unmarshaller = context.createUnmarshaller();
return (T) unmarshaller.unmarshal(source);
}
/**
* Serializes a java object to the xml representation.
*
* @param value
* java object
* @return xml string
* @throws JAXBException
* could happen
*/
public String serialize(final T value) throws JAXBException {
final Marshaller marshaller = context.createMarshaller();
final StringWriter buffer = new StringWriter();
marshaller.marshal(createElement(value), buffer);
return buffer.toString();
}
/**
* Serializes a java object to a xml sink.
*
* @param value
* java object
* @param result
* transform sink
* @throws JAXBException
* could happen
*/
public void serialize(final T value, final Result result) throws JAXBException {
final Marshaller marshaller = context.createMarshaller();
marshaller.marshal(createElement(value), result);
}
/**
* creates a jax element for a given java object.
*
* @param value
* java object
* @return jaxb element
*/
protected JAXBElement<T> createElement(final T value) {
final XmlRootElement ann = findAnnotation(XmlRootElement.class, clazz);
return new JAXBElement<T>(new QName(ann.namespace(), ann.name()), this.clazz, null, value);
}
/**
* recursively searches a given annotation.
*
* @param <T>
* annotation type
* @param annotation
* annotation to search
* @param clazz
* root of the class hierarchy.
* @return annotation
*/
private <X extends Annotation> X findAnnotation(final Class<X> annotation, final Class<?> clazz) {
if (clazz == null)
return null;
final X ann = clazz.getAnnotation(annotation);
if (ann != null)
return ann;
for (Class<?> iface : clazz.getInterfaces()) {
final X iann = findAnnotation(annotation, iface);
if (iann != null)
return iann;
}
final X parent = findAnnotation(annotation, clazz.getSuperclass());
if (parent != null)
return parent;
return null;
}
public JAXBContext getContext() {
return context;
}
public void setContext(final JAXBContext context) {
this.context = context;
}
public Class<? extends T> getClazz() {
return clazz;
}
public void setClazz(final Class<T> clazz) {
this.clazz = clazz;
}
}