com.google.sitebricks.client.transport.JacksonJsonTransportWithConverters Maven / Gradle / Ivy
package com.google.sitebricks.client.transport;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Set;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.deser.CustomDeserializerFactory;
import org.codehaus.jackson.map.deser.StdDeserializerProvider;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.primitives.Primitives;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.sitebricks.conversion.Converter;
import com.google.sitebricks.conversion.ConverterRegistry;
import com.google.sitebricks.conversion.StandardTypeConverter;
import com.google.sitebricks.conversion.generics.Generics;
/**
* @author Dhanji R. Prasanna ([email protected])
* @author John Patterson ([email protected])
* @author JRodriguez
*/
@Singleton
public class JacksonJsonTransportWithConverters extends Json {
private final ObjectMapper objectMapper;
private Collection> exceptions = Sets.newHashSet();
@Inject
public JacksonJsonTransportWithConverters(ConverterRegistry registry) {
this.objectMapper = new ObjectMapper();
CustomDeserializerFactory deserializerFactory = new CustomDeserializerFactory();
// leave these for Jackson to handle
exceptions.add(String.class);
exceptions.add(Object.class);
exceptions.addAll(Primitives.allWrapperTypes());
//
Multimap typeToConverterDirection = ArrayListMultimap.create();
addConverterDirections(registry, true, typeToConverterDirection);
addConverterDirections(registry, false, typeToConverterDirection);
createJacksonDeserializers(deserializerFactory, typeToConverterDirection);
objectMapper.setDeserializerProvider(new StdDeserializerProvider(deserializerFactory));
}
public ObjectMapper getObjectMapper() {
return objectMapper;
}
// keep track of which direction we want to use
private static class ConverterDirection
{
Converter, ?> converter;
boolean forward;
}
private void addConverterDirections(ConverterRegistry registry, boolean forward, Multimap typeToConverterDirections) {
Multimap> typeToConverters = forward ? registry.getConvertersByTarget() : registry.getConvertersBySource();
Set types = typeToConverters.keySet();
for (Type type : types) {
if (exceptions.contains(type)) continue;
Collection> converters = typeToConverters.get(type);
for (Converter, ?> converter : converters) {
ConverterDirection converterDirection = new ConverterDirection();
converterDirection.converter = converter;
converterDirection.forward = forward;
typeToConverterDirections.put(type, converterDirection);
}
}
}
private void createJacksonDeserializers(CustomDeserializerFactory deserializerFactory, Multimap typeToConverterDirections)
{
Set targetTypes = typeToConverterDirections.keySet();
for (Type targetType : targetTypes) {
Collection converterDirections = typeToConverterDirections.get(targetType);
Class> targetClass = Generics.erase(targetType);
ConvertersDeserializer jds = new ConvertersDeserializer(converterDirections);
typesafeAddMapping(targetClass, jds, deserializerFactory);
}
}
@SuppressWarnings("unchecked")
private void typesafeAddMapping(Class> type, JsonDeserializer deserializer,
CustomDeserializerFactory factory) {
factory.addSpecificMapping((Class) type, deserializer);
}
public T in(InputStream in, Class type) throws IOException {
return objectMapper.readValue(in, type);
}
public void out(OutputStream out, Class type, T data) {
try {
objectMapper.writeValue(out, data);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public class ConvertersDeserializer extends JsonDeserializer