package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.*;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.NullValueProvider;
import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.type.LogicalType;
import com.fasterxml.jackson.databind.util.AccessPattern;
@SuppressWarnings("rawtypes")
public class EnumSetDeserializer
extends StdDeserializer<EnumSet<?>>
implements ContextualDeserializer
{
private static final long serialVersionUID = 1L;
protected final JavaType _enumType;
protected JsonDeserializer<Enum<?>> _enumDeserializer;
protected final NullValueProvider _nullProvider;
protected final boolean _skipNullValues;
protected final Boolean _unwrapSingle;
@SuppressWarnings("unchecked" )
public EnumSetDeserializer(JavaType enumType, JsonDeserializer<?> deser)
{
super(EnumSet.class);
_enumType = enumType;
if (!enumType.isEnumType()) {
throw new IllegalArgumentException("Type "+enumType+" not Java Enum type");
}
_enumDeserializer = (JsonDeserializer<Enum<?>>) deser;
_unwrapSingle = null;
_nullProvider = null;
_skipNullValues = false;
}
@Deprecated
protected EnumSetDeserializer(EnumSetDeserializer base,
JsonDeserializer<?> deser, Boolean unwrapSingle) {
this(base, deser, base._nullProvider, unwrapSingle);
}
@SuppressWarnings("unchecked" )
protected EnumSetDeserializer(EnumSetDeserializer base,
JsonDeserializer<?> deser, NullValueProvider nuller, Boolean unwrapSingle) {
super(base);
_enumType = base._enumType;
_enumDeserializer = (JsonDeserializer<Enum<?>>) deser;
_nullProvider = nuller;
_skipNullValues = NullsConstantProvider.isSkipper(nuller);
_unwrapSingle = unwrapSingle;
}
public EnumSetDeserializer withDeserializer(JsonDeserializer<?> deser) {
if (_enumDeserializer == deser) {
return this;
}
return new EnumSetDeserializer(this, deser, _nullProvider, _unwrapSingle);
}
@Deprecated
public EnumSetDeserializer withResolved(JsonDeserializer<?> deser, Boolean unwrapSingle) {
return withResolved(deser, _nullProvider, unwrapSingle);
}
public EnumSetDeserializer withResolved(JsonDeserializer<?> deser, NullValueProvider nuller,
Boolean unwrapSingle) {
if ((Objects.equals(_unwrapSingle, unwrapSingle)) && (_enumDeserializer == deser) && (_nullProvider == deser)) {
return this;
}
return new EnumSetDeserializer(this, deser, nuller, unwrapSingle);
}
@Override
public boolean isCachable() {
if (_enumType.getValueHandler() != null) {
return false;
}
return true;
}
@Override
public LogicalType logicalType() {
return LogicalType.Collection;
}
@Override
public Boolean supportsUpdate(DeserializationConfig config) {
return Boolean.TRUE;
}
@Override
public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
return constructSet();
}
@Override
public AccessPattern getEmptyAccessPattern() {
return AccessPattern.DYNAMIC;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
final Boolean unwrapSingle = findFormatFeature(ctxt, property, EnumSet.class,
JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
JsonDeserializer<?> deser = _enumDeserializer;
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(_enumType, property);
} else {
deser = ctxt.handleSecondaryContextualization(deser, property, _enumType);
}
return withResolved(deser, findContentNullProvider(ctxt, property, deser), unwrapSingle);
}
@Override
public EnumSet<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
EnumSet result = constructSet();
if (!p.isExpectedStartArrayToken()) {
return handleNonArray(p, ctxt, result);
}
return _deserialize(p, ctxt, result);
}
@Override
public EnumSet<?> deserialize(JsonParser p, DeserializationContext ctxt,
EnumSet<?> result) throws IOException
{
if (!p.isExpectedStartArrayToken()) {
return handleNonArray(p, ctxt, result);
}
return _deserialize(p, ctxt, result);
}
@SuppressWarnings("unchecked")
protected final EnumSet<?> _deserialize(JsonParser p, DeserializationContext ctxt,
EnumSet result) throws IOException
{
JsonToken t;
try {
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
Enum<?> value;
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = (Enum<?>) _nullProvider.getNullValue(ctxt);
} else {
value = _enumDeserializer.deserialize(p, ctxt);
}
if (value != null) {
result.add(value);
}
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
@Override
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException
{
return typeDeserializer.deserializeTypedFromArray(p, ctxt);
}
@SuppressWarnings("unchecked")
private EnumSet constructSet()
{
return EnumSet.noneOf((Class<Enum>) _enumType.getRawClass());
}
@SuppressWarnings("unchecked")
protected EnumSet<?> handleNonArray(JsonParser p, DeserializationContext ctxt,
EnumSet result)
throws IOException
{
boolean canWrap = (_unwrapSingle == Boolean.TRUE) ||
((_unwrapSingle == null) &&
ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
if (!canWrap) {
return (EnumSet<?>) ctxt.handleUnexpectedToken(EnumSet.class, p);
}
if (p.hasToken(JsonToken.VALUE_NULL)) {
return (EnumSet<?>) ctxt.handleUnexpectedToken(_enumType, p);
}
try {
Enum<?> value = _enumDeserializer.deserialize(p, ctxt);
if (value != null) {
result.add(value);
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
}