package com.fasterxml.jackson.databind.deser;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdResolver;
import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.util.ClassUtil;
public abstract class DefaultDeserializationContext
extends DeserializationContext
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected transient LinkedHashMap<ObjectIdGenerator.IdKey, ReadableObjectId> _objectIds;
private List<ObjectIdResolver> _objectIdResolvers;
protected DefaultDeserializationContext(DeserializerFactory df, DeserializerCache cache) {
super(df, cache);
}
protected DefaultDeserializationContext(DefaultDeserializationContext src,
DeserializationConfig config, JsonParser p, InjectableValues values) {
super(src, config, p, values);
}
protected DefaultDeserializationContext(DefaultDeserializationContext src,
DeserializationConfig config) {
super(src, config);
}
protected DefaultDeserializationContext(DefaultDeserializationContext src,
DeserializerFactory factory) {
super(src, factory);
}
protected DefaultDeserializationContext(DefaultDeserializationContext src) {
super(src);
}
public DefaultDeserializationContext copy() {
throw new IllegalStateException("DefaultDeserializationContext sub-class not overriding copy()");
}
@Override
public ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> gen, ObjectIdResolver resolverType)
{
if (id == null) {
return null;
}
final ObjectIdGenerator.IdKey key = gen.key(id);
if (_objectIds == null) {
_objectIds = new LinkedHashMap<ObjectIdGenerator.IdKey,ReadableObjectId>();
} else {
ReadableObjectId entry = _objectIds.get(key);
if (entry != null) {
return entry;
}
}
ObjectIdResolver resolver = null;
if (_objectIdResolvers == null) {
_objectIdResolvers = new ArrayList<ObjectIdResolver>(8);
} else {
for (ObjectIdResolver res : _objectIdResolvers) {
if (res.canUseFor(resolverType)) {
resolver = res;
break;
}
}
}
if (resolver == null) {
resolver = resolverType.newForDeserialization(this);
_objectIdResolvers.add(resolver);
}
ReadableObjectId entry = createReadableObjectId(key);
entry.setResolver(resolver);
_objectIds.put(key, entry);
return entry;
}
protected ReadableObjectId createReadableObjectId(IdKey key) {
return new ReadableObjectId(key);
}
@Override
public void checkUnresolvedObjectId() throws UnresolvedForwardReference
{
if (_objectIds == null) {
return;
}
if (!isEnabled(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)) {
return;
}
UnresolvedForwardReference exception = null;
for (Entry<IdKey,ReadableObjectId> entry : _objectIds.entrySet()) {
ReadableObjectId roid = entry.getValue();
if (!roid.hasReferringProperties()) {
continue;
}
if (tryToResolveUnresolvedObjectId(roid)) {
continue;
}
if (exception == null) {
exception = new UnresolvedForwardReference(getParser(), "Unresolved forward references for: ");
}
Object key = roid.getKey().key;
for (Iterator<Referring> iterator = roid.referringProperties(); iterator.hasNext(); ) {
Referring referring = iterator.next();
exception.addUnresolvedId(key, referring.getBeanType(), referring.getLocation());
}
}
if (exception != null) {
throw exception;
}
}
protected boolean tryToResolveUnresolvedObjectId(ReadableObjectId roid)
{
return roid.tryToResolveUnresolved(this);
}
@SuppressWarnings("unchecked")
@Override
public JsonDeserializer<Object> deserializerInstance(Annotated ann, Object deserDef)
throws JsonMappingException
{
if (deserDef == null) {
return null;
}
JsonDeserializer<?> deser;
if (deserDef instanceof JsonDeserializer) {
deser = (JsonDeserializer<?>) deserDef;
} else {
if (!(deserDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
}
Class<?> deserClass = (Class<?>)deserDef;
if (deserClass == JsonDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) {
return null;
}
if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
}
HandlerInstantiator hi = _config.getHandlerInstantiator();
deser = (hi == null) ? null : hi.deserializerInstance(_config, ann, deserClass);
if (deser == null) {
deser = (JsonDeserializer<?>) ClassUtil.createInstance(deserClass,
_config.canOverrideAccessModifiers());
}
}
if (deser instanceof ResolvableDeserializer) {
((ResolvableDeserializer) deser).resolve(this);
}
return (JsonDeserializer<Object>) deser;
}
@Override
public final KeyDeserializer keyDeserializerInstance(Annotated ann, Object deserDef)
throws JsonMappingException
{
if (deserDef == null) {
return null;
}
KeyDeserializer deser;
if (deserDef instanceof KeyDeserializer) {
deser = (KeyDeserializer) deserDef;
} else {
if (!(deserDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
+deserDef.getClass().getName()
+"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
}
Class<?> deserClass = (Class<?>)deserDef;
if (deserClass == KeyDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) {
return null;
}
if (!KeyDeserializer.class.isAssignableFrom(deserClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()
+"; expected Class<KeyDeserializer>");
}
HandlerInstantiator hi = _config.getHandlerInstantiator();
deser = (hi == null) ? null : hi.keyDeserializerInstance(_config, ann, deserClass);
if (deser == null) {
deser = (KeyDeserializer) ClassUtil.createInstance(deserClass,
_config.canOverrideAccessModifiers());
}
}
if (deser instanceof ResolvableDeserializer) {
((ResolvableDeserializer) deser).resolve(this);
}
return deser;
}
public abstract DefaultDeserializationContext with(DeserializerFactory factory);
public abstract DefaultDeserializationContext createInstance(
DeserializationConfig config, JsonParser p, InjectableValues values);
public abstract DefaultDeserializationContext createDummyInstance(
DeserializationConfig config);
public Object readRootValue(JsonParser p, JavaType valueType,
JsonDeserializer<Object> deser, Object valueToUpdate)
throws IOException
{
if (_config.useRootWrapping()) {
return _unwrapAndDeserialize(p, valueType, deser, valueToUpdate);
}
if (valueToUpdate == null) {
return deser.deserialize(p, this);
}
return deser.deserialize(p, this, valueToUpdate);
}
protected Object _unwrapAndDeserialize(JsonParser p,
JavaType rootType, JsonDeserializer<Object> deser,
Object valueToUpdate)
throws IOException
{
PropertyName expRootName = _config.findRootName(rootType);
String expSimpleName = expRootName.getSimpleName();
if (p.currentToken() != JsonToken.START_OBJECT) {
reportWrongTokenException(rootType, JsonToken.START_OBJECT,
"Current token not START_OBJECT (needed to unwrap root name %s), but %s",
ClassUtil.name(expSimpleName), p.currentToken());
}
if (p.nextToken() != JsonToken.FIELD_NAME) {
reportWrongTokenException(rootType, JsonToken.FIELD_NAME,
"Current token not FIELD_NAME (to contain expected root name %s), but %s",
ClassUtil.name(expSimpleName), p.currentToken());
}
String actualName = p.currentName();
if (!expSimpleName.equals(actualName)) {
reportPropertyInputMismatch(rootType, actualName,
"Root name (%s) does not match expected (%s) for type %s",
ClassUtil.name(actualName), ClassUtil.name(expSimpleName), ClassUtil.getTypeDescription(rootType));
}
p.nextToken();
final Object result;
if (valueToUpdate == null) {
result = deser.deserialize(p, this);
} else {
result = deser.deserialize(p, this, valueToUpdate);
}
if (p.nextToken() != JsonToken.END_OBJECT) {
reportWrongTokenException(rootType, JsonToken.END_OBJECT,
"Current token not END_OBJECT (to match wrapper object with root name %s), but %s",
ClassUtil.name(expSimpleName), p.currentToken());
}
return result;
}
public final static class Impl extends DefaultDeserializationContext
{
private static final long serialVersionUID = 1L;
public Impl(DeserializerFactory df) {
super(df, null);
}
private Impl(Impl src,
DeserializationConfig config, JsonParser p, InjectableValues values) {
super(src, config, p, values);
}
private Impl(Impl src) { super(src); }
private Impl(Impl src, DeserializerFactory factory) {
super(src, factory);
}
private Impl(Impl src, DeserializationConfig config) {
super(src, config);
}
@Override
public DefaultDeserializationContext copy() {
ClassUtil.verifyMustOverride(Impl.class, this, "copy");
return new Impl(this);
}
@Override
public DefaultDeserializationContext createInstance(DeserializationConfig config,
JsonParser p, InjectableValues values) {
return new Impl(this, config, p, values);
}
@Override
public DefaultDeserializationContext createDummyInstance(DeserializationConfig config) {
return new Impl(this, config);
}
@Override
public DefaultDeserializationContext with(DeserializerFactory factory) {
return new Impl(this, factory);
}
}
}