org.ocelotds.core.services.ArgumentConvertor.java Source code

Java tutorial

Introduction

Here is the source code for org.ocelotds.core.services.ArgumentConvertor.java

Source

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.ocelotds.core.services;

import org.ocelotds.marshalling.ArgumentServices;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.ArrayType;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.SimpleType;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import javax.inject.Inject;
import org.ocelotds.Constants;
import org.ocelotds.annotations.OcelotLogger;
import org.ocelotds.marshalling.exceptions.JsonMarshallerException;
import org.ocelotds.marshalling.IJsonMarshaller;
import org.ocelotds.marshalling.annotations.JsonMarshallerType;
import org.ocelotds.marshalling.annotations.JsonUnmarshaller;
import org.ocelotds.marshalling.exceptions.JsonUnmarshallingException;
import org.slf4j.Logger;

/**
 *
 * @author hhfrancois
 */
public class ArgumentConvertor implements IArgumentConvertor {

    @Inject
    @OcelotLogger
    private Logger logger;

    @Inject
    ObjectMapper objectMapper;

    @Inject
    ArgumentServices argumentServices;

    /**
     * Convert json to Java
     *
     * @param jsonArg
     * @param paramType
     * @param parameterAnnotations
     * @return
     * @throws org.ocelotds.marshalling.exceptions.JsonUnmarshallingException
     * @throws org.ocelotds.marshalling.exceptions.JsonMarshallerException
     */
    @Override
    public Object convertJsonToJava(String jsonArg, Type paramType, Annotation[] parameterAnnotations)
            throws JsonUnmarshallingException, JsonMarshallerException {
        if ("null".equals(jsonArg)) {
            return null;
        }
        JsonUnmarshaller juma = getJsonUnmarshallerAnnotation(parameterAnnotations);
        if (null != juma) {
            Object result = getResult(jsonArg, argumentServices.getIJsonMarshallerInstance(juma.value()),
                    juma.type());
            argumentServices.checkType(result, paramType);
            return result;
        } else {
            return convertArgument(jsonArg, paramType);
        }
    }

    Object getResult(String jsonArg, IJsonMarshaller ijm, JsonMarshallerType type)
            throws JsonUnmarshallingException {
        Object result;
        switch (type) {
        case LIST:
            result = argumentServices.getJavaResultFromSpecificUnmarshallerIterable(jsonArg, ijm);
            break;
        case MAP:
            result = argumentServices.getJavaResultFromSpecificUnmarshallerMap(jsonArg, ijm);
            break;
        default:
            result = ijm.toJava(jsonArg);
        }
        return result;
    }

    /**
     * return the JsonUnmarshaller annotation
     *
     * @param annotations
     * @return
     */
    JsonUnmarshaller getJsonUnmarshallerAnnotation(Annotation[] annotations) {
        for (Annotation annotation : annotations) {
            if (JsonUnmarshaller.class.isInstance(annotation)) {
                return (JsonUnmarshaller) annotation;
            }
        }
        return null;
    }

    /**
     * If argument is annotated with JsonUnmarshaller annotation, get the JsonUnmarshaller class
     *
     * @param annotations
     * @param paramType
     * @return
     */
    Class<? extends IJsonMarshaller> getMarshallerAnnotation(Annotation[] annotations) {
        JsonUnmarshaller ju = getJsonUnmarshallerAnnotation(annotations);
        return (ju != null) ? ju.value() : null;
    }

    /**
     * try to convert json argument in java type
     *
     * @param arg
     * @param paramType
     * @return
     * @throws IllegalArgumentException
     */
    Object convertArgument(String arg, Type paramType) throws IllegalArgumentException {
        Object result = null;
        if (null == arg || "null".equals(arg)) {
            return result;
        }
        logger.debug("Try to convert {} : param = {} : {}", new Object[] { arg, paramType, paramType.getClass() });
        try { // GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType, Class
            if (ParameterizedType.class.isInstance(paramType)) {
                JavaType javaType = getJavaType(paramType);
                logger.debug("Try to convert '{}'to JavaType : '{}'", arg, paramType);
                result = getObjectMapper().readValue(arg, javaType);
                logger.debug("Conversion of '{}'to '{}' : OK", arg, paramType);
            } else if (Class.class.isInstance(paramType)) {
                Class cls = (Class) paramType;
                logger.debug("Try to convert '{}' to Class '{}'", arg, paramType);
                checkStringArgument(cls, arg);
                result = getObjectMapper().readValue(arg, cls);
                logger.debug("Conversion of '{}'to '{}' : OK", arg, paramType);
            } else { // GenericArrayType, TypeVariable<D>, WildcardType
                logger.warn("Conversion of '{}'to '{}' not yet supported", arg, paramType);
            }
        } catch (IOException ex) {
            logger.debug("Conversion of '{}' to '{}' failed", arg, paramType);
            throw new IllegalArgumentException(paramType.toString());
        }
        return result;
    }

    /**
     * check if class and argument are string
     *
     * @param cls
     * @param arg
     * @throws IOException
     */
    void checkStringArgument(Class cls, String arg) throws IOException {
        if (arg.startsWith(Constants.QUOTE)) { // ca ressemble  une string
            if (!cls.equals(String.class)) { // et on veut pas une string
                throw new IOException();
            }
        } else // ca ressemble pas  une string
        if (cls.equals(String.class)) { // mais on veut une string
            throw new IOException();
        }
    }

    private JavaType getJavaType(Type type) {
        Class clazz;
        logger.debug("Computing type of {} - {}", type.getClass(), type.toString());
        if (type instanceof ParameterizedType) {
            clazz = (Class) ((ParameterizedType) type).getRawType();
        } else {
            clazz = (Class) type;
        }
        JavaType javaType;
        Type actualType;
        if (Collection.class.isAssignableFrom(clazz)) {
            ParameterizedType pt = (ParameterizedType) type;
            actualType = pt.getActualTypeArguments()[0];
            JavaType t1 = getJavaType(actualType);
            javaType = CollectionType.construct(Collection.class, t1);
        } else if (clazz.isArray()) {
            Class t = clazz.getComponentType();
            JavaType t1 = getJavaType(t);
            javaType = ArrayType.construct(t1, null, null);
        } else if (Map.class.isAssignableFrom(clazz)) {
            ParameterizedType pt = (ParameterizedType) type;
            actualType = pt.getActualTypeArguments()[0];
            JavaType t1 = getJavaType(actualType);
            actualType = pt.getActualTypeArguments()[1];
            JavaType t2 = getJavaType(actualType);
            javaType = MapType.construct(Map.class, t1, t2);
        } else {
            javaType = SimpleType.construct(clazz);
        }
        return javaType;
    }

    ObjectMapper getObjectMapper() {
        return objectMapper;
    }

}