package com.fasterxml.jackson.dataformat.xml.ser;
import java.io.IOException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.PropertyName;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.SerializerFactory;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import com.fasterxml.jackson.dataformat.xml.util.StaxUtil;
import com.fasterxml.jackson.dataformat.xml.util.TypeUtil;
import com.fasterxml.jackson.dataformat.xml.util.XmlRootNameLookup;
public class XmlSerializerProvider extends DefaultSerializerProvider
{
private static final long serialVersionUID = 1L;
protected final static QName ROOT_NAME_FOR_NULL = new QName("null");
protected final XmlRootNameLookup _rootNameLookup;
public XmlSerializerProvider(XmlRootNameLookup rootNames)
{
super();
_rootNameLookup = rootNames;
}
public XmlSerializerProvider(XmlSerializerProvider src,
SerializationConfig config, SerializerFactory f)
{
super(src, config, f);
_rootNameLookup = src._rootNameLookup;
}
protected XmlSerializerProvider(XmlSerializerProvider src) {
super(src);
_rootNameLookup = new XmlRootNameLookup();
}
@Override
public DefaultSerializerProvider copy() {
return new XmlSerializerProvider(this);
}
@Override
public DefaultSerializerProvider createInstance(SerializationConfig config,
SerializerFactory jsf) {
return new XmlSerializerProvider(this, config, jsf);
}
@SuppressWarnings("resource")
@Override
public void serializeValue(JsonGenerator gen, Object value) throws IOException
{
if (value == null) {
_serializeXmlNull(gen);
return;
}
final Class<?> cls = value.getClass();
final boolean asArray;
final ToXmlGenerator xgen = _asXmlGenerator(gen);
if (xgen == null) {
asArray = false;
} else {
QName rootName = _rootNameFromConfig();
if (rootName == null) {
rootName = _rootNameLookup.findRootName(cls, _config);
}
_initWithRootName(xgen, rootName);
asArray = TypeUtil.isIndexedType(cls);
if (asArray) {
_startRootArray(xgen, rootName);
}
}
final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
try {
ser.serialize(value, gen, this);
} catch (Exception e) {
throw _wrapAsIOE(gen, e);
}
if (asArray) {
gen.writeEndObject();
}
}
@SuppressWarnings("resource")
@Override
public void serializeValue(JsonGenerator gen, Object value, JavaType rootType,
JsonSerializer<Object> ser) throws IOException
{
if (value == null) {
_serializeXmlNull(gen);
return;
}
final boolean asArray;
final ToXmlGenerator xgen = _asXmlGenerator(gen);
if (xgen == null) {
asArray = false;
} else {
QName rootName = _rootNameFromConfig();
if (rootName == null) {
rootName = _rootNameLookup.findRootName(rootType, _config);
}
_initWithRootName(xgen, rootName);
asArray = TypeUtil.isIndexedType(rootType);
if (asArray) {
_startRootArray(xgen, rootName);
}
}
if (ser == null) {
ser = findTypedValueSerializer(rootType, true, null);
}
try {
ser.serialize(value, gen, this);
} catch (Exception e) {
throw _wrapAsIOE(gen, e);
}
if (asArray) {
gen.writeEndObject();
}
}
protected void _serializeXmlNull(JsonGenerator jgen) throws IOException
{
QName rootName = _rootNameFromConfig();
if (rootName == null) {
rootName = ROOT_NAME_FOR_NULL;
}
if (jgen instanceof ToXmlGenerator) {
_initWithRootName((ToXmlGenerator) jgen, rootName);
}
super.serializeValue(jgen, null);
}
protected void _startRootArray(ToXmlGenerator xgen, QName rootName) throws IOException
{
xgen.writeStartObject();
xgen.writeFieldName("item");
}
protected void _initWithRootName(ToXmlGenerator xgen, QName rootName) throws IOException
{
if (!xgen.setNextNameIfMissing(rootName)) {
if (xgen.inRoot()) {
xgen.setNextName(rootName);
}
}
xgen.initGenerator();
String ns = rootName.getNamespaceURI();
if (ns != null && ns.length() > 0) {
try {
xgen.getStaxWriter().setDefaultNamespace(ns);
} catch (XMLStreamException e) {
StaxUtil.throwAsGenerationException(e, xgen);
}
}
}
protected QName _rootNameFromConfig()
{
PropertyName name = _config.getFullRootName();
if (name == null) {
return null;
}
String ns = name.getNamespace();
if (ns == null || ns.isEmpty()) {
return new QName(name.getSimpleName());
}
return new QName(ns, name.getSimpleName());
}
protected ToXmlGenerator _asXmlGenerator(JsonGenerator gen)
throws JsonMappingException
{
if (!(gen instanceof ToXmlGenerator)) {
if (!(gen instanceof TokenBuffer)) {
throw JsonMappingException.from(gen,
"XmlMapper does not with generators of type other than ToXmlGenerator; got: "+gen.getClass().getName());
}
return null;
}
return (ToXmlGenerator) gen;
}
protected IOException _wrapAsIOE(JsonGenerator g, Exception e) {
if (e instanceof IOException) {
return (IOException) e;
}
String msg = e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
return new JsonMappingException(g, msg, e);
}
}