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

org.apache.ibatis.reflection.ParamNameResolver Maven / Gradle / Ivy

There is a newer version: 1.0.0-beta2
Show newest version
/**
 *    Copyright 2009-2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.apache.ibatis.reflection;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

public class ParamNameResolver {

  private static final String GENERIC_NAME_PREFIX = "param";

  /**
   * 

* The key is the index and the value is the name of the parameter.
* The name is obtained from {@link Param} if specified. When {@link Param} is not specified, * the parameter index is used. Note that this index could be different from the actual index * when the method has special parameters (i.e. {@link RowBounds} or {@link ResultHandler}). *

*
    *
  • aMethod(@Param("M") int a, @Param("N") int b) -> {{0, "M"}, {1, "N"}}
  • *
  • aMethod(int a, int b) -> {{0, "0"}, {1, "1"}}
  • *
  • aMethod(int a, RowBounds rb, int b) -> {{0, "0"}, {2, "1"}}
  • *
*/ private final SortedMap names; private boolean hasParamAnnotation; public ParamNameResolver(Configuration config, Method method) { final Class[] paramTypes = method.getParameterTypes(); final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap map = new TreeMap(); int paramCount = paramAnnotations.length; // get names from @Param annotations for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { // skip special parameters continue; } String name = null; for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { hasParamAnnotation = true; name = ((Param) annotation).value(); break; } } if (name == null) { // @Param was not specified. if (config.isUseActualParamName()) { name = getActualParamName(method, paramIndex); } if (name == null) { // use the parameter index as the name ("0", "1", ...) // gcode issue #71 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); } private String getActualParamName(Method method, int paramIndex) { if (Jdk.parameterExists) { return ParamNameUtil.getParamNames(method).get(paramIndex); } return null; } private static boolean isSpecialParameter(Class clazz) { return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz); } /** * Returns parameter names referenced by SQL providers. */ public String[] getNames() { return names.values().toArray(new String[0]); } /** *

* A single non-special parameter is returned without a name.
* Multiple parameters are named using the naming rule.
* In addition to the default names, this method also adds the generic names (param1, param2, * ...). *

*/ public Object getNamedParams(Object[] args) { final int paramCount = names.size(); if (args == null || paramCount == 0) { return null; } else if (!hasParamAnnotation && paramCount == 1) { return args[names.firstKey()]; } else { final Map param = new ParamMap(); int i = 0; for (Map.Entry entry : names.entrySet()) { param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1); // ensure not to overwrite parameter named with @Param if (!names.containsValue(genericParamName)) { param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } } }