TableSerializer.java
package tools.jackson.datatype.guava.ser;
import java.util.Map;
import java.util.Set;
import tools.jackson.core.*;
import tools.jackson.core.type.WritableTypeId;
import tools.jackson.databind.*;
import tools.jackson.databind.jsontype.TypeSerializer;
import tools.jackson.databind.ser.jdk.MapSerializer;
import tools.jackson.databind.ser.std.StdContainerSerializer;
import tools.jackson.databind.type.MapType;
import tools.jackson.databind.type.TypeFactory;
import com.google.common.collect.Table;
/**
* @author stevenmhood (via hyandell) - Initial implementation
* @author tatu - Some refactoring to streamline code
*/
public class TableSerializer
extends StdContainerSerializer<Table<?, ?, ?>>
{
/**
* Type declaration that defines parameters; may be a supertype of actual
* type of property being serialized.
*/
private final JavaType _type;
private final ValueSerializer<Object> _rowSerializer;
private final ValueSerializer<Object> _columnSerializer;
private final TypeSerializer _valueTypeSerializer;
private final ValueSerializer<Object> _valueSerializer;
private final MapSerializer _rowMapSerializer;
/*
/**********************************************************************
/* Serializer lifecycle
/**********************************************************************
*/
public TableSerializer(JavaType type)
{
super(type, null);
_type = type;
_rowSerializer = null;
_columnSerializer = null;
_valueTypeSerializer = null;
_valueSerializer = null;
_rowMapSerializer = null;
}
@SuppressWarnings( "unchecked" )
protected TableSerializer(final TableSerializer src,
final BeanProperty property,
final TypeFactory typeFactory,
final ValueSerializer<?> rowKeySerializer,
final ValueSerializer<?> columnKeySerializer,
final TypeSerializer valueTypeSerializer,
final ValueSerializer<?> valueSerializer)
{
super(src, property);
_type = src._type;
_rowSerializer = (ValueSerializer<Object>) rowKeySerializer;
_columnSerializer = (ValueSerializer<Object>) columnKeySerializer;
_valueTypeSerializer = valueTypeSerializer;
_valueSerializer = (ValueSerializer<Object>) valueSerializer;
final MapType columnAndValueType = typeFactory.constructMapType(Map.class,
_type.containedTypeOrUnknown(1), _type.containedTypeOrUnknown(2));
ValueSerializer<?> columnAndValueSerializer =
MapSerializer.construct(columnAndValueType, false,
_valueTypeSerializer,
_columnSerializer,
_valueSerializer,
null,
(Set<String>) null, (Set<String>) null);
final MapType rowMapType = typeFactory.constructMapType(Map.class,
_type.containedTypeOrUnknown(0), columnAndValueType);
_rowMapSerializer =
MapSerializer.construct(rowMapType, false,
null,
_rowSerializer,
(ValueSerializer<Object>) columnAndValueSerializer,
null,
(Set<String>) null, (Set<String>) null);
}
protected TableSerializer(final TableSerializer src, TypeSerializer typeSer)
{
super(src);
_type = src._type;
_rowSerializer = src._rowSerializer;
_columnSerializer = src._columnSerializer;
_valueTypeSerializer = typeSer;
_valueSerializer = src._valueSerializer;
_rowMapSerializer = src._rowMapSerializer;
}
protected TableSerializer withResolved(final BeanProperty property,
final TypeFactory typeFactory,
final ValueSerializer<?> rowKeySer,
final ValueSerializer<?> columnKeySer,
final TypeSerializer vts,
final ValueSerializer<?> valueSer )
{
return new TableSerializer(this, property, typeFactory,
rowKeySer, columnKeySer, vts, valueSer);
}
@Override
protected StdContainerSerializer<?> _withValueTypeSerializer(final TypeSerializer typeSer)
{
return new TableSerializer(this, typeSer);
}
@Override
public ValueSerializer<?> createContextual(final SerializationContext ctxt,
final BeanProperty property)
{
ValueSerializer<?> valueSer = _valueSerializer;
if (valueSer == null) { // if type is final, can actually resolve:
final JavaType valueType = _type.containedTypeOrUnknown(2);
if (valueType.isFinal()) {
valueSer = ctxt.findContentValueSerializer(valueType, property);
}
} else {
valueSer = ctxt.handleSecondaryContextualization(valueSer, property);
}
ValueSerializer<?> rowKeySer = _rowSerializer;
if (rowKeySer == null) {
rowKeySer = ctxt.findKeySerializer(_type.containedTypeOrUnknown(0), property);
} else {
rowKeySer = ctxt.handleSecondaryContextualization(rowKeySer, property);
}
ValueSerializer<?> columnKeySer = _columnSerializer;
if (columnKeySer == null) {
columnKeySer = ctxt.findKeySerializer(_type.containedTypeOrUnknown(1), property);
} else {
columnKeySer = ctxt.handleSecondaryContextualization(columnKeySer, property);
}
// finally, TypeSerializers may need contextualization as well
TypeSerializer typeSer = _valueTypeSerializer;
if (typeSer != null) {
typeSer = typeSer.forProperty(ctxt, property);
}
return withResolved(property, ctxt.getTypeFactory(), rowKeySer, columnKeySer, typeSer, valueSer);
}
/*
/**********************************************************************
/* Simple accessor API
/**********************************************************************
*/
@Override
public JavaType getContentType() {
return _type.getContentType();
}
@Override
public ValueSerializer<?> getContentSerializer() {
return _valueSerializer;
}
@Override
public boolean isEmpty(SerializationContext ctxt, Table<?, ?, ?> table) {
return table.isEmpty();
}
@Override
public boolean hasSingleElement(final Table<?, ?, ?> table) {
return table.size() == 1;
}
/*
/**********************************************************************
/* Main serialization methods
/**********************************************************************
*/
@Override
public void serialize(final Table<?, ?, ?> value,
final JsonGenerator gen, final SerializationContext ctxt)
throws JacksonException
{
gen.writeStartObject(value);
if (!value.isEmpty()) {
serializeEntries(value, gen, ctxt);
}
gen.writeEndObject();
}
@Override
public void serializeWithType(final Table<?, ?, ?> value,
final JsonGenerator g, final SerializationContext ctxt,
final TypeSerializer typeSer)
throws JacksonException
{
g.assignCurrentValue(value);
WritableTypeId typeIdDef = typeSer.writeTypePrefix(g, ctxt,
typeSer.typeId(value, JsonToken.START_OBJECT));
serializeEntries(value, g, ctxt);
typeSer.writeTypeSuffix(g, ctxt, typeIdDef);
}
private final void serializeEntries( final Table<?, ?, ?> table, final JsonGenerator g,
final SerializationContext ctxt)
throws JacksonException
{
_rowMapSerializer.serializeEntries(table.rowMap(), g, ctxt);
}
}