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