1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.reflection;
17
18 import java.lang.annotation.Annotation;
19 import java.lang.reflect.Method;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25 import java.util.SortedMap;
26 import java.util.TreeMap;
27
28 import org.apache.ibatis.annotations.Param;
29 import org.apache.ibatis.binding.MapperMethod.ParamMap;
30 import org.apache.ibatis.session.Configuration;
31 import org.apache.ibatis.session.ResultHandler;
32 import org.apache.ibatis.session.RowBounds;
33
34 public class ParamNameResolver {
35
36 public static final String GENERIC_NAME_PREFIX = "param";
37
38 public static final String[] GENERIC_NAME_CACHE = new String[10];
39
40 static {
41 for (int i = 0; i < 10; i++) {
42 GENERIC_NAME_CACHE[i] = GENERIC_NAME_PREFIX + (i + 1);
43 }
44 }
45
46 private final boolean useActualParamName;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 private final SortedMap<Integer, String> names;
62
63 private boolean hasParamAnnotation;
64
65 public ParamNameResolver(Configuration config, Method method) {
66 this.useActualParamName = config.isUseActualParamName();
67 final Class<?>[] paramTypes = method.getParameterTypes();
68 final Annotation[][] paramAnnotations = method.getParameterAnnotations();
69 final SortedMap<Integer, String> map = new TreeMap<>();
70 int paramCount = paramAnnotations.length;
71
72 for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
73 if (isSpecialParameter(paramTypes[paramIndex])) {
74
75 continue;
76 }
77 String name = null;
78 for (Annotation annotation : paramAnnotations[paramIndex]) {
79 if (annotation instanceof Param) {
80 hasParamAnnotation = true;
81 name = ((Param) annotation).value();
82 break;
83 }
84 }
85 if (name == null) {
86
87 if (useActualParamName) {
88 name = getActualParamName(method, paramIndex);
89 }
90 if (name == null) {
91
92
93 name = String.valueOf(map.size());
94 }
95 }
96 map.put(paramIndex, name);
97 }
98 names = Collections.unmodifiableSortedMap(map);
99 }
100
101 private String getActualParamName(Method method, int paramIndex) {
102 return ParamNameUtil.getParamNames(method).get(paramIndex);
103 }
104
105 private static boolean isSpecialParameter(Class<?> clazz) {
106 return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz);
107 }
108
109
110
111
112
113
114 public String[] getNames() {
115 return names.values().toArray(new String[0]);
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129 public Object getNamedParams(Object[] args) {
130 final int paramCount = names.size();
131 if (args == null || paramCount == 0) {
132 return null;
133 }
134 if (!hasParamAnnotation && paramCount == 1) {
135 Object value = args[names.firstKey()];
136 return wrapToMapIfCollection(value, useActualParamName ? names.get(names.firstKey()) : null);
137 } else {
138 final Map<String, Object> param = new ParamMap<>();
139 int i = 0;
140 for (Map.Entry<Integer, String> entry : names.entrySet()) {
141 param.put(entry.getValue(), args[entry.getKey()]);
142
143 final String genericParamName = i < 10 ? GENERIC_NAME_CACHE[i] : GENERIC_NAME_PREFIX + (i + 1);
144
145 if (!names.containsValue(genericParamName)) {
146 param.put(genericParamName, args[entry.getKey()]);
147 }
148 i++;
149 }
150 return param;
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166 public static Object wrapToMapIfCollection(Object object, String actualParamName) {
167 if (object instanceof Collection) {
168 ParamMap<Object> map = new ParamMap<>();
169 map.put("collection", object);
170 if (object instanceof List) {
171 map.put("list", object);
172 }
173 Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
174 return map;
175 }
176 if (object != null && object.getClass().isArray()) {
177 ParamMap<Object> map = new ParamMap<>();
178 map.put("array", object);
179 Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
180 return map;
181 }
182 return object;
183 }
184
185 }