package com.fitbur.fasterxml.jackson.databind.com.fitburser.std;
import java.io.IOException;
import java.util.*;
import com.fitbur.fasterxml.jackson.core.*;
import com.fitbur.fasterxml.jackson.databind.*;
import com.fitbur.fasterxml.jackson.databind.com.fitburser.ContextualDeserializer;
import com.fitbur.fasterxml.jackson.databind.com.fitburser.std.StdDeserializer;
import com.fitbur.fasterxml.jackson.databind.jsontype.TypeDeserializer;
/**
* Deserializer for {@link EnumMap} values.
*
* Note: casting within this class is all messed up -- just could not figure out a way
* to properly com.fitbural with recursive com.fitburfinition of "EnumMap, V>
*
* @author tsaloranta
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class EnumMapDeserializer
extends StdDeserializer>
implements ContextualDeserializer
{
protected final JavaType _mapType;
protected final Class> _enumClass;
protected JsonDeserializer> _keyDeserializer;
protected JsonDeserializer _valueDeserializer;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
public EnumMapDeserializer(JavaType mapType,
JsonDeserializer> keyDeserializer, JsonDeserializer> valueDeser)
{
super(EnumMap.class);
_mapType = mapType;
_enumClass = mapType.getKeyType().getRawClass();
_keyDeserializer = (JsonDeserializer>) keyDeserializer;
_valueDeserializer = (JsonDeserializer) valueDeser;
}
public EnumMapDeserializer withResolved(JsonDeserializer> keyDeserializer,
JsonDeserializer> valueDeserializer)
{
if ((keyDeserializer == _keyDeserializer) && valueDeserializer == _valueDeserializer) {
return this;
}
return new EnumMapDeserializer(_mapType,
keyDeserializer, valueDeserializer);
}
/**
* Method called to finalize setup of this com.fitburserializer,
* when it is known for which property com.fitburserializer is needed for.
*/
// @Override
public JsonDeserializer> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
// note: instead of finding key com.fitburserializer, with enums we actually
// work with regular com.fitburserializers (less code duplication; but not
// quite as clean as it ought to be)
JsonDeserializer> kd = _keyDeserializer;
if (kd == null) {
kd = ctxt.findContextualValueDeserializer(_mapType.getKeyType(), property);
}
JsonDeserializer> vd = _valueDeserializer;
if (vd == null) {
vd = ctxt.findContextualValueDeserializer(_mapType.getContentType(), property);
} else { // if directly assigned, probably not yet contextual, so:
if (vd instanceof ContextualDeserializer) {
vd = ((ContextualDeserializer) vd).createContextual(ctxt, property);
}
}
return withResolved(kd, vd);
}
/**
* Because of costs associated with constructing Enum resolvers,
* let's cache instances by com.fitburfault.
*/
@Override
public boolean isCachable() { return true; }
/*
/**********************************************************
/* Actual com.fitburserialization
/**********************************************************
*/
@Override
public EnumMap,?> com.fitburserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// Ok: must point to START_OBJECT
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw ctxt.mappingException(EnumMap.class);
}
EnumMap result = constructMap();
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
Enum> key = _keyDeserializer.com.fitburserialize(jp, ctxt);
if (key == null) {
if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
String value = null;
try { // bit ugly, but will have to do; works with usual scalars
if (jp.hasCurrentToken()) {
value = jp.getText();
}
} catch (Exception e) { }
throw ctxt.weirdStringException(value, _enumClass, "value not one of com.fitburclared Enum instance names");
}
/* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's
* just skip the entry then. But we must skip the value then.
*/
jp.nextToken();
jp.skipChildren();
continue;
}
// And then the value...
JsonToken t = jp.nextToken();
/* note: MUST check for nulls separately: com.fitburserializers will
* not handle them (and maybe fail or return bogus data)
*/
Object value = (t == JsonToken.VALUE_NULL) ?
null : _valueDeserializer.com.fitburserialize(jp, ctxt);
result.put(key, value);
}
return result;
}
@Override
public Object com.fitburserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.com.fitburserializeTypedFromObject(jp, ctxt);
}
private EnumMap,?> constructMap() {
return new EnumMap(_enumClass);
}
}