Package br.com.caelum.vraptor.deserialization.gson

Source Code of br.com.caelum.vraptor.deserialization.gson.GsonDeserialization

package br.com.caelum.vraptor.deserialization.gson;

import static com.google.common.base.Objects.firstNonNull;
import static com.google.common.base.Strings.isNullOrEmpty;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.caelum.vraptor.controller.ControllerMethod;
import br.com.caelum.vraptor.deserialization.Deserializer;
import br.com.caelum.vraptor.deserialization.Deserializes;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.view.ResultException;

import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
* A GSON deserializer.
* @author Renan Reis
* @author Guilherme Mangabeira
*/

@Deserializes({ "application/json", "json" })
public class GsonDeserialization implements Deserializer {

  private static final Logger logger = LoggerFactory.getLogger(GsonDeserialization.class);

  private ParameterNameProvider paramNameProvider;
  private Instance<JsonDeserializer<?>> adapters;
  private HttpServletRequest request;

  @Deprecated // CDI eyes only
  public GsonDeserialization() {
  }
 
  @Inject
  public GsonDeserialization(ParameterNameProvider paramNameProvider, @Any Instance<JsonDeserializer<?>> adapters,
      HttpServletRequest request) {
    this.paramNameProvider = paramNameProvider;
    this.adapters = adapters;
    this.request = request;
  }

  @Override
  public Object[] deserialize(InputStream inputStream, ControllerMethod method) {
    Class<?>[] types = getTypes(method);
    Type[] pTypes = method.getMethod().getGenericParameterTypes();
   
    if (types.length == 0) {
      throw new IllegalArgumentException("Methods that consumes representations must receive just one argument");
    }

    Gson gson = getGson();
   
    Object[] params = new Object[types.length];
    String[] parameterNames = paramNameProvider.parameterNamesFor(method.getMethod());

    try {
      String content = getContentOfStream(inputStream);
      logger.debug("json retrieved: {}", content);
     
      if (!isNullOrEmpty(content)) {
        JsonParser parser = new JsonParser();
        JsonElement jsonElement = parser.parse(content);
        if (jsonElement.isJsonObject()) {
          JsonObject root = jsonElement.getAsJsonObject();
   
          for (int i = 0; i < types.length; i++) {
            String name = parameterNames[i];
            JsonElement node = root.get(name);
           
            if (isWithoutRoot(parameterNames, root)) {
              params[i] = gson.fromJson(root, types[i]);
              logger.info("json without root deserialized");
              break;

            } else if (node != null) {
              if (node.isJsonArray()) {
                JsonArray jsonArray= node.getAsJsonArray();
                if (pTypes[i] instanceof ParameterizedType)
                  params[i] = gson.fromJson(jsonArray, pTypes[i]);
                else
                  params[i] = gson.fromJson(jsonArray, types[i]);
              } else {
                params[i] = gson.fromJson(node, types[i]);
              }
            }

            logger.debug("json deserialized: {}", params[i]);
          }
        } else if (jsonElement.isJsonArray()) {
          if ((pTypes.length != 1) || (!(pTypes[0] instanceof ParameterizedType)))
            throw new IllegalArgumentException("Methods that consumes an array representation must receive only just one collection generic typed argument");

          JsonArray jsonArray= jsonElement.getAsJsonArray();
         
          params[0] = gson.fromJson(jsonArray, pTypes[0]);
         
          logger.debug("array json deserialized: {}", params[0]);
        } else {
          throw new IllegalArgumentException("This is an invalid or not supported json content");
        }
      }
    } catch (Exception e) {
      throw new ResultException("Unable to deserialize data", e);
    }

    return params;
  }

  protected Gson getGson() {
    GsonBuilder builder = new GsonBuilder();

    for (JsonDeserializer<?> adapter : adapters) {
      builder.registerTypeHierarchyAdapter(getAdapterType(adapter), adapter);
    }

    return builder.create();
  }

  private Class<?> getAdapterType(JsonDeserializer<?> adapter) {
    Type[] genericInterfaces = adapter.getClass().getGenericInterfaces();
    ParameterizedType type = (ParameterizedType) genericInterfaces[0];
    Type actualType = type.getActualTypeArguments()[0];

    if (actualType instanceof ParameterizedType)
      return (Class<?>) ((ParameterizedType) actualType).getRawType();
    else
      return (Class<?>) actualType;
  }

  private String getContentOfStream(InputStream input) throws IOException {
    String charset = getRequestCharset();
    logger.debug("Using charset {}", charset);

    return CharStreams.toString(new InputStreamReader(input, charset));
  }

  private String getRequestCharset() {
    String charset = firstNonNull(request.getHeader("Accept-Charset"), "UTF-8");
    return charset.split(",")[0];
  }

  private boolean isWithoutRoot(String[] parameterNames, JsonObject root) {
    for (String parameterName : parameterNames) {
      if (root.get(parameterName) != null)
        return false;
    }
    return true;
  }

  protected Class<?>[] getTypes(ControllerMethod method) {
    Class<?>[] parameterTypes = method.getMethod().getParameterTypes();
    Type genericType = getGenericSuperClass(method);
    if (genericType != null) {
      return parseGenericParameters(parameterTypes, genericType);
    }

    return parameterTypes;
  }

  private Class<?>[] parseGenericParameters(Class<?>[] parameterTypes,
      Type genericType) {
    Class<?> type = (Class<?>) getGenericType(genericType);
    for (int i = 0; i < parameterTypes.length; i++) {
      if (parameterTypes[i].isAssignableFrom(type)) {
        parameterTypes[i] = type;
      }
    }
    return parameterTypes;
  }

  private Type getGenericSuperClass(ControllerMethod method) {
    Type genericType = method.getController().getType().getGenericSuperclass();
    if (genericType instanceof ParameterizedType) {
      return genericType;
    }

    return null;
  }

  private Type getGenericType(Type type) {
    ParameterizedType paramType = (ParameterizedType) type;
    return paramType.getActualTypeArguments()[0];
  }
}
TOP

Related Classes of br.com.caelum.vraptor.deserialization.gson.GsonDeserialization

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.