Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.prestosql.jdbc.$internal.jackson.datatype.guava.ser.MultimapSerializer Maven / Gradle / Ivy
package io.prestosql.jdbc.$internal.jackson.datatype.guava.ser;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import io.prestosql.jdbc.$internal.jackson.annotation.JsonFormat;
import io.prestosql.jdbc.$internal.jackson.annotation.JsonIgnoreProperties;
import io.prestosql.jdbc.$internal.jackson.core.*;
import io.prestosql.jdbc.$internal.jackson.core.type.WritableTypeId;
import io.prestosql.jdbc.$internal.jackson.databind.*;
import io.prestosql.jdbc.$internal.jackson.databind.introspect.AnnotatedMember;
import io.prestosql.jdbc.$internal.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import io.prestosql.jdbc.$internal.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import io.prestosql.jdbc.$internal.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
import io.prestosql.jdbc.$internal.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import io.prestosql.jdbc.$internal.jackson.databind.jsonFormatVisitors.JsonMapFormatVisitor;
import io.prestosql.jdbc.$internal.jackson.databind.jsontype.TypeSerializer;
import io.prestosql.jdbc.$internal.jackson.databind.ser.ContainerSerializer;
import io.prestosql.jdbc.$internal.jackson.databind.ser.ContextualSerializer;
import io.prestosql.jdbc.$internal.jackson.databind.ser.PropertyFilter;
import io.prestosql.jdbc.$internal.jackson.databind.ser.impl.PropertySerializerMap;
import io.prestosql.jdbc.$internal.jackson.databind.ser.std.MapProperty;
import io.prestosql.jdbc.$internal.jackson.databind.type.MapLikeType;
import io.prestosql.jdbc.$internal.guava.collect.Multimap;
/**
* Serializer for Guava's {@link Multimap} values. Output format encloses all
* value sets in JSON Array, regardless of number of values; this to reduce
* complexity (and inaccuracy) of trying to handle cases where values themselves
* would be serialized as arrays (in which cases determining whether given array
* is a wrapper or value gets complicated and unreliable).
*
* Missing features, compared to standard Java Maps:
*
* Inclusion checks for content entries (non-null, non-empty)
*
* Sorting of entries
*
*
*/
public class MultimapSerializer
extends ContainerSerializer>
implements ContextualSerializer
{
private static final long serialVersionUID = 1L;
private final MapLikeType _type;
private final BeanProperty _property;
private final JsonSerializer _keySerializer;
private final TypeSerializer _valueTypeSerializer;
private final JsonSerializer _valueSerializer;
/**
* Set of entries to omit during serialization, if any
*
* @since 2.5
*/
protected final Set _ignoredEntries;
/**
* If value type can not be statically determined, mapping from
* runtime value types to serializers are stored in this object.
*
* @since 2.5
*/
protected PropertySerializerMap _dynamicValueSerializers;
/**
* Id of the property filter to use, if any; null if none.
*
* @since 2.5
*/
protected final Object _filterId;
/**
* Flag set if output is forced to be sorted by keys (usually due
* to annotation).
*
* NOTE: not yet used.
*
* @since 2.5
*/
protected final boolean _sortKeys;
public MultimapSerializer(MapLikeType type, BeanDescription beanDesc,
JsonSerializer keySerializer, TypeSerializer vts, JsonSerializer valueSerializer,
Set ignoredEntries, Object filterId)
{
super(type.getRawClass(), false);
_type = type;
_property = null;
_keySerializer = keySerializer;
_valueTypeSerializer = vts;
_valueSerializer = valueSerializer;
_ignoredEntries = ignoredEntries;
_filterId = filterId;
_sortKeys = false;
_dynamicValueSerializers = PropertySerializerMap.emptyForProperties();
}
/**
* @since 2.5
*/
@SuppressWarnings("unchecked")
protected MultimapSerializer(MultimapSerializer src, BeanProperty property,
JsonSerializer keySerializer, TypeSerializer vts, JsonSerializer valueSerializer,
Set ignoredEntries, Object filterId, boolean sortKeys)
{
super(src);
_type = src._type;
_property = property;
_keySerializer = (JsonSerializer) keySerializer;
_valueTypeSerializer = vts;
_valueSerializer = (JsonSerializer) valueSerializer;
_dynamicValueSerializers = src._dynamicValueSerializers;
_ignoredEntries = ignoredEntries;
_filterId = filterId;
_sortKeys = sortKeys;
}
protected MultimapSerializer withResolved(BeanProperty property,
JsonSerializer keySer, TypeSerializer vts, JsonSerializer valueSer,
Set ignored, Object filterId, boolean sortKeys)
{
return new MultimapSerializer(this, property, keySer, vts, valueSer,
ignored, filterId, sortKeys);
}
@Override
protected ContainerSerializer _withValueTypeSerializer(TypeSerializer typeSer) {
return new MultimapSerializer(this, _property, _keySerializer,
typeSer, _valueSerializer, _ignoredEntries, _filterId, _sortKeys);
}
/*
/**********************************************************
/* Post-processing (contextualization)
/**********************************************************
*/
@Override
public JsonSerializer createContextual(SerializerProvider provider,
BeanProperty property) throws JsonMappingException
{
JsonSerializer valueSer = _valueSerializer;
if (valueSer == null) { // if type is final, can actually resolve:
JavaType valueType = _type.getContentType();
if (valueType.isFinal()) {
valueSer = provider.findValueSerializer(valueType, property);
}
} else if (valueSer instanceof ContextualSerializer) {
valueSer = ((ContextualSerializer) valueSer).createContextual(provider, property);
}
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember();
JsonSerializer keySer = null;
Object filterId = _filterId;
// First: if we have a property, may have property-annotation overrides
if (propertyAcc != null && intr != null) {
Object serDef = intr.findKeySerializer(propertyAcc);
if (serDef != null) {
keySer = provider.serializerInstance(propertyAcc, serDef);
}
serDef = intr.findContentSerializer(propertyAcc);
if (serDef != null) {
valueSer = provider.serializerInstance(propertyAcc, serDef);
}
filterId = intr.findFilterId(propertyAcc);
}
if (valueSer == null) {
valueSer = _valueSerializer;
}
// [datatype-guava#124]: May have a content converter
valueSer = findContextualConvertingSerializer(provider, property, valueSer);
if (valueSer == null) {
// One more thing -- if explicit content type is annotated,
// we can consider it a static case as well.
JavaType valueType = _type.getContentType();
if (valueType.useStaticType()) {
valueSer = provider.findValueSerializer(valueType, property);
}
} else {
valueSer = provider.handleSecondaryContextualization(valueSer, property);
}
if (keySer == null) {
keySer = _keySerializer;
}
if (keySer == null) {
keySer = provider.findKeySerializer(_type.getKeyType(), property);
} else {
keySer = provider.handleSecondaryContextualization(keySer, property);
}
// finally, TypeSerializers may need contextualization as well
TypeSerializer typeSer = _valueTypeSerializer;
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
}
Set ignored = _ignoredEntries;
boolean sortKeys = false;
if (intr != null && propertyAcc != null) {
JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(propertyAcc);
if (ignorals != null) {
Set newIgnored = ignorals.findIgnoredForSerialization();
if ((newIgnored != null) && !newIgnored.isEmpty()) {
ignored = (ignored == null) ? new HashSet() : new HashSet<>(ignored);
for (String str : newIgnored) {
ignored.add(str);
}
}
}
Boolean b = intr.findSerializationSortAlphabetically(propertyAcc);
sortKeys = (b != null) && b.booleanValue();
}
// 19-May-2016, tatu: Also check per-property format features, even if
// this isn't yet used (as per [guava#7])
JsonFormat.Value format = findFormatOverrides(provider, property, handledType());
if (format != null) {
Boolean B = format.getFeature(JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES);
if (B != null) {
sortKeys = B.booleanValue();
}
}
return withResolved(property, keySer, typeSer, valueSer,
ignored, filterId, sortKeys);
}
/*
/**********************************************************
/* Accessors for ContainerSerializer
/**********************************************************
*/
@Override
public JsonSerializer getContentSerializer() {
return _valueSerializer;
}
@Override
public JavaType getContentType() {
return _type.getContentType();
}
@Override
public boolean hasSingleElement(Multimap map) {
return map.size() == 1;
}
@Override
public boolean isEmpty(SerializerProvider prov, Multimap value) {
return value.isEmpty();
}
/*
/**********************************************************
/* Post-processing (contextualization)
/**********************************************************
*/
@Override
public void serialize(Multimap value, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
gen.writeStartObject();
// [databind#631]: Assign current value, to be accessible by custom serializers
gen.setCurrentValue(value);
if (!value.isEmpty()) {
// 20-Mar-2017, tatu: And this is where [datatypes-collections#7] would be
// plugged in...
// if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
// value = _orderEntries(value, gen, provider);
// }
if (_filterId != null) {
serializeFilteredFields(value, gen, provider);
} else {
serializeFields(value, gen, provider);
}
}
gen.writeEndObject();
}
@Override
public void serializeWithType(Multimap value, JsonGenerator gen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException
{
gen.setCurrentValue(value);
WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
typeSer.typeId(value, JsonToken.START_OBJECT));
if (!value.isEmpty()) {
// 20-Mar-2017, tatu: And this is where [datatypes-collections#7] would be
// plugged in...
// if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
// value = _orderEntries(value, gen, provider);
// }
if (_filterId != null) {
serializeFilteredFields(value, gen, provider);
} else {
serializeFields(value, gen, provider);
}
}
typeSer.writeTypeSuffix(gen, typeIdDef);
}
private final void serializeFields(Multimap mmap, JsonGenerator
gen, SerializerProvider provider)
throws IOException
{
final Set ignored = _ignoredEntries;
PropertySerializerMap serializers = _dynamicValueSerializers;
for (Entry> entry : mmap.asMap().entrySet()) {
// First, serialize key
Object key = entry.getKey();
if ((ignored != null) && ignored.contains(key)) {
continue;
}
if (key == null) {
provider.findNullKeySerializer(_type.getKeyType(), _property)
.serialize(null, gen, provider);
} else {
_keySerializer.serialize(key, gen, provider);
}
// note: value is a List, but generic type is for contents... so:
gen.writeStartArray();
for (Object vv : entry.getValue()) {
if (vv == null) {
provider.defaultSerializeNull(gen);
continue;
}
JsonSerializer valueSer = _valueSerializer;
if (valueSer == null) {
Class cc = vv.getClass();
valueSer = serializers.serializerFor(cc);
if (valueSer == null) {
valueSer = _findAndAddDynamic(serializers, cc, provider);
serializers = _dynamicValueSerializers;
}
}
if (_valueTypeSerializer == null) {
valueSer.serialize(vv, gen, provider);
} else {
valueSer.serializeWithType(vv, gen, provider, _valueTypeSerializer);
}
}
gen.writeEndArray();
}
}
private final void serializeFilteredFields(Multimap mmap, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
final Set ignored = _ignoredEntries;
PropertyFilter filter = findPropertyFilter(provider, _filterId, mmap);
final MapProperty prop = new MapProperty(_valueTypeSerializer, _property);
for (Entry> entry : mmap.asMap().entrySet()) {
// First, serialize key
Object key = entry.getKey();
if ((ignored != null) && ignored.contains(key)) {
continue;
}
Collection value = entry.getValue();
JsonSerializer valueSer;
if (value == null) {
// !!! TODO: null suppression?
valueSer = provider.getDefaultNullValueSerializer();
} else {
valueSer = _valueSerializer;
}
prop.reset(key, value, _keySerializer, valueSer);
try {
filter.serializeAsField(mmap, gen, provider, prop);
} catch (Exception e) {
String keyDesc = ""+key;
wrapAndThrow(provider, e, value, keyDesc);
}
}
}
/*
/**********************************************************
/* Schema related functionality
/**********************************************************
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
JsonMapFormatVisitor v2 = (visitor == null) ? null : visitor.expectMapFormat(typeHint);
if (v2 != null) {
v2.keyFormat(_keySerializer, _type.getKeyType());
JsonSerializer valueSer = _valueSerializer;
final JavaType vt = _type.getContentType();
final SerializerProvider prov = visitor.getProvider();
if (valueSer == null) {
valueSer = _findAndAddDynamic(_dynamicValueSerializers, vt, prov);
}
final JsonSerializer valueSer2 = valueSer;
v2.valueFormat(new JsonFormatVisitable() {
final JavaType arrayType = prov.getTypeFactory().constructArrayType(vt);
@Override
public void acceptJsonFormatVisitor(
JsonFormatVisitorWrapper v3, JavaType hint3)
throws JsonMappingException
{
JsonArrayFormatVisitor v4 = v3.expectArrayFormat(arrayType);
if (v4 != null) {
v4.itemsFormat(valueSer2, vt);
}
}
}, vt);
}
}
/*
/**********************************************************
/* Internal helper methods
/**********************************************************
*/
protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map,
Class type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
// did we get a new map of serializers? If so, start using it
if (map != result.map) {
_dynamicValueSerializers = result.map;
}
return result.serializer;
}
protected final JsonSerializer _findAndAddDynamic(PropertySerializerMap map,
JavaType type, SerializerProvider provider) throws JsonMappingException
{
PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, _property);
if (map != result.map) {
_dynamicValueSerializers = result.map;
}
return result.serializer;
}
}