com.jsftoolkit.utils.serial.DomSerializerManagerImpl Maven / Gradle / Ivy
package com.jsftoolkit.utils.serial;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.jsftoolkit.utils.ClassUtils;
/**
* This class is safe for concurrent use by multiple threads. It is not a
* singleton because it may be configured with different serializers.
*
*
* @author noah
*
*/
public class DomSerializerManagerImpl implements DomSerializerManager {
private Map serializers = new HashMap();
private Map> domSerializers = new HashMap>();
private DocumentBuilder builder;
/**
* Creates a new instance with the default {@link DocumentBuilder}.
*
* @see #DomSerializerManagerImpl()
*
* @throws ParserConfigurationException
* if a {@link DocumentBuilder} cannot be created.
*/
public DomSerializerManagerImpl() throws ParserConfigurationException {
this(DocumentBuilderFactory.newInstance().newDocumentBuilder());
}
/**
* Creates a new instance with {@link Serializer}s for primitive types,
* {@link File}s, {@link Class}es, and {@link URL}s already registered.
* Additionally, an {@link AnnotatedObjectDomSerializer} is registered.
*
*/
@SuppressWarnings("unchecked")
public DomSerializerManagerImpl(DocumentBuilder builder) {
AbstractSerializer[] known = { new BooleanSerializer(),
new CharSequenceSerializer(), new ClassSerializer(),
new FileSerializer(), new NumberSerializer(),
new URLSerializer() };
for (AbstractSerializer serializer : known) {
register(serializer.getFromClass(), serializer);
}
register(Object.class, new AnnotatedObjectDomSerializer());
this.builder = builder;
}
/**
* Registers a {@link Serializer} for the given class.
*
* @param serializer
*/
public void register(Class clazz, Serializer serializer) {
serializers.put(clazz, serializer);
}
/**
* Register a {@link DomSerializer} for the given class.
*
* @param
* @param clazz
* @param serializer
*/
public void register(Class clazz, DomSerializer serializer) {
domSerializers.put(clazz, serializer);
}
/**
*
* @param clazz
* @return a {@link Serializer} for clazz, a super type of clazz or an
* interface of clazz.
*/
public Serializer findSerializer(Class clazz) {
Map map = serializers;
return internalFind(clazz, map);
}
/**
* Looks for a mapping in map corresponding to clazz, a super class of
* clazz, or an interface of clazz, searched in that order. The first
* non-null value is returned.
*
* @param
* @param clazz
* @param map
* @return
*/
protected T internalFind(Class clazz, Map map) {
if (clazz.isPrimitive()) {
clazz = ClassUtils.box(clazz);
}
Class[] interfaces = clazz.getInterfaces();
while (clazz != null) {
T t = map.get(clazz);
if (t == null) {
clazz = clazz.getSuperclass();
} else {
return t;
}
}
for (Class _interface : interfaces) {
T t = map.get(_interface);
if (t != null) {
return t;
}
}
return null;
}
/**
*
* @param obj
* @return obj converted to a {@link Document}
*/
public Document toDocument(Object obj) {
Document doc = builder.newDocument();
doc.appendChild(nextToDom(obj, doc));
return doc;
}
/*
* (non-Javadoc)
*
* @see com.jsftoolkit.utils.serial.DomSerializerManager#nextToDom(java.lang.Object,
* org.w3c.dom.Document)
*/
@SuppressWarnings("unchecked")
public Node nextToDom(Object obj, Document doc) {
if (obj == null) {
return null;
}
Class extends Object> clazz = obj.getClass();
Serializer serializer = findSerializer(clazz);
if (serializer == null) {
// can't get a NPE here because this class is a DomSerializer for
// Object
return findDomSerializer(clazz).toDom(obj, doc, this);
} else {
// if there is a serializer, create a text node
return doc.createTextNode(serializer.serialize(obj));
}
}
/**
*
* @param clazz
* @return a {@link DomSerializer} for the given class or a superclass or
* interface of that class.
*/
@SuppressWarnings("unchecked")
public DomSerializer