package com.fasterxml.jackson.dataformat.xml;
import java.io.IOException;
import java.util.Collection;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
import com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver;
import com.fasterxml.jackson.databind.jsontype.impl.MinimalClassNameIdResolver;
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.dataformat.xml.util.StaxUtil;
public class XmlTypeResolverBuilder extends StdTypeResolverBuilder
{
@Override
public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes)
{
super.init(idType, idRes);
if (_typeProperty != null) {
_typeProperty = StaxUtil.sanitizeXmlTypeName(_typeProperty);
}
return this;
}
@Override
public StdTypeResolverBuilder typeProperty(String typeIdPropName)
{
if (typeIdPropName == null || typeIdPropName.length() == 0) {
typeIdPropName = _idType.getDefaultPropertyName();
}
_typeProperty = StaxUtil.sanitizeXmlTypeName(typeIdPropName);
return this;
}
@Override
protected TypeIdResolver idResolver(MapperConfig<?> config,
JavaType baseType, PolymorphicTypeValidator subtypeValidator,
Collection<NamedType> subtypes, boolean forSer, boolean forDeser)
{
if (_customIdResolver != null) {
return _customIdResolver;
}
switch (_idType) {
case CLASS:
return new XmlClassNameIdResolver(baseType, config.getTypeFactory(),
subTypeValidator(config));
case MINIMAL_CLASS:
return new XmlMinimalClassNameIdResolver(baseType, config.getTypeFactory(),
subTypeValidator(config));
default:
}
return super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
}
protected static String encodeXmlClassName(String className)
{
int ix = className.lastIndexOf('$');
if (ix >= 0) {
StringBuilder sb = new StringBuilder(className);
do {
sb.replace(ix, ix+1, "..");
ix = className.lastIndexOf('$', ix-1);
} while (ix >= 0);
className = sb.toString();
}
return className;
}
protected static String decodeXmlClassName(String className)
{
int ix = className.lastIndexOf("..");
if (ix >= 0) {
StringBuilder sb = new StringBuilder(className);
do {
sb.replace(ix, ix+2, "$");
ix = className.lastIndexOf("..", ix-1);
} while (ix >= 0);
className = sb.toString();
}
return className;
}
protected static class XmlClassNameIdResolver
extends ClassNameIdResolver
{
public XmlClassNameIdResolver(JavaType baseType, TypeFactory typeFactory,
PolymorphicTypeValidator ptv)
{
super(baseType, typeFactory, ptv);
}
@Override
public String idFromValue(Object value)
{
return encodeXmlClassName(super.idFromValue(value));
}
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
return super.typeFromId(context, decodeXmlClassName(id));
}
}
protected static class XmlMinimalClassNameIdResolver
extends MinimalClassNameIdResolver
{
public XmlMinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory,
PolymorphicTypeValidator ptv)
{
super(baseType, typeFactory, ptv);
}
@Override
public String idFromValue(Object value)
{
return encodeXmlClassName(super.idFromValue(value));
}
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
return super.typeFromId(context, decodeXmlClassName(id));
}
}
}