org.mousepilots.es.maven.model.generator.model.attribute.GenericMethodInfo.java Source code

Java tutorial

Introduction

Here is the source code for org.mousepilots.es.maven.model.generator.model.attribute.GenericMethodInfo.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.mousepilots.es.maven.model.generator.model.attribute;

import edu.emory.mathcs.backport.java.util.Arrays;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.mousepilots.es.core.util.Function;
import org.mousepilots.es.core.util.StringUtils;

/**
 * Determines the generic return and exception-types of a method as fully qualified strings. Generic methods may be polymorphic: their return types
 * or arguments 
 * @author geenenju
 */
public class GenericMethodInfo {

    private final Method method;

    private final Map<TypeVariable<?>, Type> typeVariable2Value;

    private final String returnType;

    private final List<String> parameterTypes, exceptionTypes;

    /**
     * Resolves the generic {@code type}
     * @param typeVariable2Value
     * @param type
     * @return 
     */
    private String getGenericTypeString(Type type) {
        if (type instanceof Class) {
            //(raw) class
            return ((Class) type).getCanonicalName();
        } else if (type instanceof ParameterizedType) {
            // e.g. Map<K,V>
            final ParameterizedType parameterizedType = (ParameterizedType) type;
            return getGenericTypeString(parameterizedType.getRawType()) + "<"
                    + StringUtils.join(Arrays.asList(parameterizedType.getActualTypeArguments()),
                            (Type actualTypeArgument) -> getGenericTypeString(actualTypeArgument), ",")
                    + ">";

        } else if (type instanceof TypeVariable) {
            //e.g. T
            final TypeVariable<?> typeVariable = (TypeVariable) type;
            final Type typeVariableValue = typeVariable2Value.get(typeVariable);
            if (typeVariableValue == null) {
                return typeVariable.getName();
            } else {
                return getGenericTypeString(typeVariableValue);
            }
        } else if (type instanceof GenericArrayType) {
            //e.g. T[]
            final GenericArrayType genericArrayType = (GenericArrayType) type;
            return getGenericTypeString(genericArrayType.getGenericComponentType()) + "[]";
        } else {
            throw new IllegalArgumentException("unsupported type " + type);
        }
    }

    /**
     * 
     * @param hasMethod the class having the {@code method}. The method may be inherited or declared.
     * @param method the {@code method} on {@code hasMethod}
     */
    public GenericMethodInfo(Class hasMethod, Method method) {
        this.method = method;
        this.typeVariable2Value = TypeUtils.getTypeArguments(hasMethod, Object.class);
        this.returnType = getGenericTypeString(this.method.getGenericReturnType());
        this.exceptionTypes = Function.apply(this.method.getGenericExceptionTypes(),
                (Type et) -> getGenericTypeString(et));
        this.parameterTypes = Function.apply(this.method.getGenericParameterTypes(),
                (Type et) -> getGenericTypeString(et));

    }

    public List<String> getParameterTypes() {
        return parameterTypes;
    }

    public String getReturnType() {
        return returnType;
    }

    public List<String> getExceptionTypes() {
        return exceptionTypes;
    }
}