Package com.google.sitebricks.client.transport

Source Code of com.google.sitebricks.client.transport.JacksonJsonTransport$ConvertersDeserializer

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 (dhanji@gmail.com)
* @author John Patterson (jdpatterson@gmail.com)
* @author JRodriguez
*/
@Singleton
public class JacksonJsonTransport extends Json {

  private final ObjectMapper objectMapper;
  private Collection<Class<?>> exceptions = Sets.newHashSet();
 
  @Inject
  public JacksonJsonTransport(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<Type, ConverterDirection> 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<Type, ConverterDirection> typeToConverterDirections) {
    Multimap<Type, Converter<?, ?>> typeToConverters = forward ? registry.getConvertersByTarget() : registry.getConvertersBySource();
    Set<Type> types = typeToConverters.keySet();
    for (Type type : types) {
      if (exceptions.contains(type)) continue;
      Collection<Converter<?, ?>> 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<Type, ConverterDirection> typeToConverterDirections)
  {
    Set<Type> targetTypes = typeToConverterDirections.keySet();
    for (Type targetType : targetTypes) {
      Collection<ConverterDirection> converterDirections = typeToConverterDirections.get(targetType);
      Class<?> targetClass = Generics.erase(targetType);
      ConvertersDeserializer jds = new ConvertersDeserializer(converterDirections);
      typesafeAddMapping(targetClass, jds, deserializerFactory);
    }
  }

  @SuppressWarnings("unchecked")
  private <T> void typesafeAddMapping(Class<?> type, JsonDeserializer<T> deserializer,
      CustomDeserializerFactory factory) {
    factory.addSpecificMapping((Class<T>) type, deserializer);
  }

  public <T> T in(InputStream in, Class<T> type) throws IOException {
    return objectMapper.readValue(in, type);
  }

  public <T> void out(OutputStream out, Class<T> type, T data) {
    try {
      objectMapper.writeValue(out, data);
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public class ConvertersDeserializer extends JsonDeserializer<Object> {

    private final Collection<ConverterDirection> converterDirections;

    public ConvertersDeserializer(Collection<ConverterDirection> converterDirections) {
      this.converterDirections = converterDirections;
    }

    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {

      Object source = getSourceObject(jp, ctxt);
     
      for (ConverterDirection converterDirection : converterDirections) {
       
        Type sourceType = converterDirection.forward ?
            StandardTypeConverter.sourceType(converterDirection.converter) :
            StandardTypeConverter.targetType(converterDirection.converter);
           
        // assume that Jackson only gives us non-generic types
        Class<?> converterSourceClass = Generics.erase(sourceType);
       
        if (converterSourceClass.isAssignableFrom(source.getClass())) {
          return converterDirection.forward ?
              StandardTypeConverter.typeSafeTo(converterDirection.converter, source) :
              StandardTypeConverter.typeSafeFrom(converterDirection.converter, source);
        }
      }

      throw new IllegalStateException("Cannot convert from " + source);
    }

    private Object getSourceObject(JsonParser jp, DeserializationContext ctxt) throws JsonParseException, IOException {
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.VALUE_NUMBER_INT) {
          return jp.getLongValue();
        }
        else if (t == JsonToken.VALUE_NUMBER_FLOAT) {
          return jp.getDoubleValue();
        }
        else if (t == JsonToken.VALUE_TRUE) {
          return Boolean.TRUE;
        }
        else if (t == JsonToken.VALUE_FALSE) {
            return Boolean.FALSE;
        }
        else if (t == JsonToken.VALUE_STRING) {
          return jp.getText();
        }
        else throw new IllegalStateException();
    }
  }
}
TOP

Related Classes of com.google.sitebricks.client.transport.JacksonJsonTransport$ConvertersDeserializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.