All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.nomou.mybatis.builder.spi.Parameters Maven / Gradle / Ivy

package com.github.nomou.mybatis.builder.spi;

import com.github.nomou.mybatis.util.Collections2;
import freework.reflect.Types;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.reflection.ParamNameResolver;
import org.apache.ibatis.session.Configuration;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

public class Parameters implements Iterable {
    /**
     * @see org.apache.ibatis.reflection.ParamNameResolver#GENERIC_NAME_PREFIX
     */
    public static final String GENERIC_NAME_PREFIX = "param";

    private final Method declaringMethod;
    private final List parameters;
    private final boolean annotated;
    private final Configuration configuration;

    public Parameters(final Method declaringMethod, final Class runtimeType, final Configuration configuration, final Class... excludes) {
        this(declaringMethod, runtimeType, configuration, Collections2.newImmutableSet(excludes));
    }

    public Parameters(final Method declaringMethod, final Class runtimeType, final Configuration configuration, final Set> excludeClasses) {
        boolean annotated = false;
        final Type[] parameterTypes = declaringMethod.getGenericParameterTypes();
        final List parameters = new ArrayList(parameterTypes.length);
        for (int index = 0; index < parameterTypes.length; index++) {
            Class parameterClass;
            final Type parameterType = Types.resolveType(parameterTypes[index], runtimeType);
            if (parameterType instanceof Class) {
                parameterClass = (Class) parameterType;
            } else if (parameterType instanceof ParameterizedType) {
                parameterClass = (Class) ((ParameterizedType) parameterType).getRawType();
            } else {
                parameterClass = declaringMethod.getParameterTypes()[index];
            }
            if (isExcludeType(parameterClass, excludeClasses)) {
                continue;
            }
            /*-
             * @see org.apache.ibatis.reflection.ParamNameResolver.ParamNameResolver
             */
            final Parameter parameter = new Parameter(declaringMethod, index, parameterType, configuration.isUseActualParamName());
            if (null != parameter.getAnnotation(Param.class)) {
                annotated = true;
            }
            parameters.add(parameter);
        }
        this.declaringMethod = declaringMethod;
        this.parameters = Collections.unmodifiableList(parameters);
        this.annotated = annotated;
        this.configuration = configuration;
    }

    public int size() {
        return parameters.size();
    }

    public boolean isEmpty() {
        return parameters.isEmpty();
    }

    public Method getDeclaringMethod() {
        return declaringMethod;
    }

    public List getParameters() {
        return Collections.unmodifiableList(parameters);
    }

    /**
     * 获取所有参数名称, 如果参数名称无法获取但'required=true'则使用其在当前参数队列中的索引作为其名称.
     *
     * @param required 是否必须
     * @return 参数名称
     */
    public String[] getParameterNames(final boolean required) {
        final String[] names = new String[parameters.size()];
        for (int index = 0; index < names.length; index++) {
            final String name = parameters.get(index).getName();
            names[index] = null != name || !required ? name : String.valueOf(index);
        }
        return names;
    }

    public Class[] getParameterTypes() {
        final Class[] types = new Class[parameters.size()];
        for (int i = 0; i < types.length; i++) {
            types[i] = parameters.get(i).getType();
        }
        return types;
    }

    /**
     * 获取mybatis调用时的参数类型.
     *
     * 

对于mapper接口中方法的非特殊参数, mybatis会转换为一个参数.

* * @return mybatis 调用时的参数类型, 如果没有参数返回null, 只有一个参数返回参数类型, 有多个参数返回{@link MapperMethod.ParamMap} * @see org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#getParameterType(Method) * @see org.apache.ibatis.reflection.ParamNameUtil */ public Class getInvokeParameterType() { Class invokeParameterType = null; final Class[] parameterTypes = getParameterTypes(); if (1 == parameterTypes.length) { invokeParameterType = parameterTypes[0]; } else if (1 < parameterTypes.length) { invokeParameterType = MapperMethod.ParamMap.class; } return invokeParameterType; } /** * 获取调用mapper时传递的参数在内部调用时使用的参数对象. * * @param args 实际传递的参数 * @return 调用时使用的参数对象 */ public Object getInvokeParameterObject(final Object[] args) { final List parameterNames = Arrays.asList(getParameterNames(true)); final List parameters = getParameters(); if (null == args || 0 == parameterNames.size()) { return null; } else if (!annotated && 1 == parameterNames.size()) { return args[parameters.iterator().next().getIndex()]; } else { final Map paramsMap = new MapperMethod.ParamMap(); for (int index = 0; index < parameterNames.size(); index++) { final String genericName = GENERIC_NAME_PREFIX + (index + 1); paramsMap.put(parameterNames.get(index), args[parameters.get(index).getIndex()]); if (!parameterNames.contains(genericName)) { paramsMap.put(genericName, args[parameters.get(index).getIndex()]); } } return paramsMap; } } /** * {@inheritDoc} */ @Override public Iterator iterator() { return parameters.iterator(); } public ParamNameResolver asParamNameResolver() { return new ParamNameResolver(configuration, declaringMethod) { @Override public String[] getNames() { return getParameterNames(true); } @Override public Object getNamedParams(final Object[] args) { return getInvokeParameterObject(args); } }; } private static boolean isExcludeType(final Class clazz, final Set> excludeClasses) { for (final Class excludeClass : excludeClasses) { if (excludeClass.isAssignableFrom(clazz)) { return true; } } return false; } }