com.fasterxml.jackson.dataformat.xml.deser.XmlBeanDeserializerModifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swagger-all Show documentation
Show all versions of swagger-all Show documentation
swagger-all is a rebundled verison of Swagger as one OSGi bundle.
package com.fasterxml.jackson.dataformat.xml.deser;
import java.util.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
/**
* The main reason for a modifier is to support handling of
* 'wrapped' Collection types.
*/
public class XmlBeanDeserializerModifier
extends BeanDeserializerModifier
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
/**
* Virtual name used for text segments.
*/
protected String _cfgNameForTextValue = "";
public XmlBeanDeserializerModifier(String nameForTextValue)
{
_cfgNameForTextValue = nameForTextValue;
}
@Override
public List updateProperties(DeserializationConfig config,
BeanDescription beanDesc, List propDefs)
{
final AnnotationIntrospector intr = config.getAnnotationIntrospector();
int changed = 0;
for (int i = 0, propCount = propDefs.size(); i < propCount; ++i) {
BeanPropertyDefinition prop = propDefs.get(i);
AnnotatedMember acc = prop.getPrimaryMember();
// should not be null, but just in case:
if (acc == null) {
continue;
}
/* First: handle "as text"? Such properties
* are exposed as values of 'unnamed' fields; so one way to
* map them is to rename property to have name ""... (and
* hope this does not break other parts...)
*/
Boolean b = AnnotationUtil.findIsTextAnnotation(intr, acc);
if (b != null && b.booleanValue()) {
// unwrapped properties will appear as 'unnamed' (empty String)
BeanPropertyDefinition newProp = prop.withSimpleName(_cfgNameForTextValue);
if (newProp != prop) {
propDefs.set(i, newProp);
}
continue;
}
// second: do we need to handle wrapping (for Lists)?
PropertyName wrapperName = prop.getWrapperName();
if (wrapperName != null && wrapperName != PropertyName.NO_NAME) {
String localName = wrapperName.getSimpleName();
if ((localName != null && localName.length() > 0)
&& !localName.equals(prop.getName())) {
// make copy-on-write as necessary
if (changed == 0) {
propDefs = new ArrayList(propDefs);
}
++changed;
propDefs.set(i, prop.withSimpleName(localName));
continue;
}
// otherwise unwrapped; needs handling but later on
}
}
return propDefs;
}
@Override
public JsonDeserializer> modifyDeserializer(DeserializationConfig config,
BeanDescription beanDesc, JsonDeserializer> deser0)
{
if (!(deser0 instanceof BeanDeserializerBase)) {
return deser0;
}
/* 17-Aug-2013, tatu: One important special case first: if we have one "XML Text"
* property, it may be exposed as VALUE_STRING token (depending on whether any attribute
* values are exposed): and to deserialize from that, we need special handling unless POJO
* has appropriate single-string creator method.
*/
BeanDeserializerBase deser = (BeanDeserializerBase) deser0;
// Heuristics are bit tricky; but for now let's assume that if POJO
// can already work with VALUE_STRING, it's ok and doesn't need extra support
if (!deser.getValueInstantiator().canCreateFromString()) {
SettableBeanProperty textProp = _findSoleTextProp(config, deser.properties());
if (textProp != null) {
return new XmlTextDeserializer(deser, textProp);
}
}
return new WrapperHandlingDeserializer(deser);
}
private SettableBeanProperty _findSoleTextProp(DeserializationConfig config,
Iterator propIt)
{
final AnnotationIntrospector ai = config.getAnnotationIntrospector();
SettableBeanProperty textProp = null;
while (propIt.hasNext()) {
SettableBeanProperty prop = propIt.next();
AnnotatedMember m = prop.getMember();
if (m != null) {
// Ok, let's use a simple check: we should have renamed it earlier so:
PropertyName n = prop.getFullName();
if (_cfgNameForTextValue.equals(n.getSimpleName())) {
// should we verify we only got one?
textProp = prop;
continue;
}
// as-attribute are ok as well
Boolean b = AnnotationUtil.findIsAttributeAnnotation(ai, m);
if (b != null && b.booleanValue()) {
continue;
}
}
// Otherwise, it's something else; no go
return null;
}
return textProp;
}
}