• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / ibatis-2 / 730

28 Dec 2025 10:16PM UTC coverage: 65.615% (+0.5%) from 65.146%
730

push

github

web-flow
Update README.md

1602 of 2802 branches covered (57.17%)

5053 of 7701 relevant lines covered (65.61%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.67
/src/main/java/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java
1
/*
2
 * Copyright 2004-2025 the original author or authors.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *    https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.ibatis.sqlmap.engine.mapping.parameter;
17

18
import com.ibatis.common.beans.Probe;
19
import com.ibatis.common.beans.ProbeFactory;
20
import com.ibatis.common.resources.Resources;
21
import com.ibatis.sqlmap.client.SqlMapException;
22
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
23
import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
24
import com.ibatis.sqlmap.engine.type.CustomTypeHandler;
25
import com.ibatis.sqlmap.engine.type.DomTypeMarker;
26
import com.ibatis.sqlmap.engine.type.TypeHandler;
27
import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
28

29
import java.util.ArrayList;
30
import java.util.List;
31
import java.util.StringTokenizer;
32

33
/**
34
 * The Class InlineParameterMapParser.
35
 */
36
public class InlineParameterMapParser {
1✔
37

38
  /** The Constant PROBE. */
39
  private static final Probe PROBE = ProbeFactory.getProbe();
1✔
40

41
  /** The Constant PARAMETER_TOKEN. */
42
  private static final String PARAMETER_TOKEN = "#";
43

44
  /** The Constant PARAM_DELIM. */
45
  private static final String PARAM_DELIM = ":";
46

47
  /**
48
   * Parses the inline parameter map.
49
   *
50
   * @param typeHandlerFactory
51
   *          the type handler factory
52
   * @param sqlStatement
53
   *          the sql statement
54
   *
55
   * @return the sql text
56
   */
57
  public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement) {
58
    return parseInlineParameterMap(typeHandlerFactory, sqlStatement, null);
1✔
59
  }
60

61
  /**
62
   * Parses the inline parameter map.
63
   *
64
   * @param typeHandlerFactory
65
   *          the type handler factory
66
   * @param sqlStatement
67
   *          the sql statement
68
   * @param parameterClass
69
   *          the parameter class
70
   *
71
   * @return the sql text
72
   */
73
  public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement,
74
      Class parameterClass) {
75

76
    String newSql = sqlStatement;
1✔
77

78
    List mappingList = new ArrayList<>();
1✔
79

80
    StringTokenizer parser = new StringTokenizer(sqlStatement, PARAMETER_TOKEN, true);
1✔
81
    StringBuilder newSqlBuffer = new StringBuilder();
1✔
82

83
    String token = null;
1✔
84
    String lastToken = null;
1✔
85
    while (parser.hasMoreTokens()) {
1✔
86
      token = parser.nextToken();
1✔
87
      if (PARAMETER_TOKEN.equals(lastToken)) {
1✔
88
        if (PARAMETER_TOKEN.equals(token)) {
1!
89
          newSqlBuffer.append(PARAMETER_TOKEN);
×
90
          token = null;
×
91
        } else {
92
          ParameterMapping mapping = null;
1✔
93
          if (token.indexOf(PARAM_DELIM) > -1) {
1✔
94
            mapping = oldParseMapping(token, parameterClass, typeHandlerFactory);
1✔
95
          } else {
96
            mapping = newParseMapping(token, parameterClass, typeHandlerFactory);
1✔
97
          }
98

99
          mappingList.add(mapping);
1✔
100
          newSqlBuffer.append("?");
1✔
101
          boolean hasMoreTokens = parser.hasMoreTokens();
1✔
102
          if (hasMoreTokens) {
1✔
103
            token = parser.nextToken();
1✔
104
          }
105
          if (!hasMoreTokens || !PARAMETER_TOKEN.equals(token)) {
1!
106
            throw new SqlMapException(
1✔
107
                "Unterminated inline parameter in mapped statement near '" + newSqlBuffer.toString() + "'");
1✔
108
          }
109
          token = null;
1✔
110
        }
1✔
111
      } else {
112
        if (!PARAMETER_TOKEN.equals(token)) {
1✔
113
          newSqlBuffer.append(token);
1✔
114
        }
115
      }
116

117
      lastToken = token;
1✔
118
    }
119

120
    newSql = newSqlBuffer.toString();
1✔
121

122
    ParameterMapping[] mappingArray = (ParameterMapping[]) mappingList
1✔
123
        .toArray(new ParameterMapping[mappingList.size()]);
1✔
124

125
    SqlText sqlText = new SqlText();
1✔
126
    sqlText.setText(newSql);
1✔
127
    sqlText.setParameterMappings(mappingArray);
1✔
128
    return sqlText;
1✔
129
  }
130

131
  /**
132
   * New parse mapping.
133
   *
134
   * @param token
135
   *          the token
136
   * @param parameterClass
137
   *          the parameter class
138
   * @param typeHandlerFactory
139
   *          the type handler factory
140
   *
141
   * @return the parameter mapping
142
   */
143
  private ParameterMapping newParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) {
144
    ParameterMapping mapping = new ParameterMapping();
1✔
145

146
    // #propertyName,javaType=string,jdbcType=VARCHAR,mode=IN,nullValue=N/A,handler=string,numericScale=2#
147

148
    StringTokenizer paramParser = new StringTokenizer(token, "=,", false);
1✔
149
    mapping.setPropertyName(paramParser.nextToken());
1✔
150

151
    while (paramParser.hasMoreTokens()) {
1✔
152
      String field = paramParser.nextToken();
1✔
153
      if (paramParser.hasMoreTokens()) {
1!
154
        String value = paramParser.nextToken();
1✔
155
        if ("javaType".equals(field)) {
1✔
156
          value = typeHandlerFactory.resolveAlias(value);
1✔
157
          mapping.setJavaTypeName(value);
1✔
158
        } else if ("jdbcType".equals(field)) {
1✔
159
          mapping.setJdbcTypeName(value);
1✔
160
        } else if ("mode".equals(field)) {
1!
161
          mapping.setMode(value);
×
162
        } else if ("nullValue".equals(field)) {
1!
163
          mapping.setNullValue(value);
1✔
164
        } else if ("handler".equals(field)) {
×
165
          try {
166
            value = typeHandlerFactory.resolveAlias(value);
×
167
            Object impl = Resources.instantiate(value);
×
168
            if (impl instanceof TypeHandlerCallback) {
×
169
              mapping.setTypeHandler(new CustomTypeHandler((TypeHandlerCallback) impl));
×
170
            } else if (impl instanceof TypeHandler) {
×
171
              mapping.setTypeHandler((TypeHandler) impl);
×
172
            } else {
173
              throw new SqlMapException(
×
174
                  "The class " + value + " is not a valid implementation of TypeHandler or TypeHandlerCallback");
175
            }
176
          } catch (Exception e) {
×
177
            throw new SqlMapException("Error loading class specified by handler field in " + token + ".  Cause: " + e,
×
178
                e);
179
          }
×
180
        } else if ("numericScale".equals(field)) {
×
181
          try {
182
            Integer numericScale = Integer.valueOf(value);
×
183
            if (numericScale.intValue() < 0) {
×
184
              throw new SqlMapException("Value specified for numericScale must be greater than or equal to zero");
×
185
            }
186
            mapping.setNumericScale(numericScale);
×
187
          } catch (NumberFormatException e) {
×
188
            throw new SqlMapException("Value specified for numericScale is not a valid Integer");
×
189
          }
×
190
        } else {
191
          throw new SqlMapException("Unrecognized parameter mapping field: '" + field + "' in " + token);
×
192
        }
193
      } else {
1✔
194
        throw new SqlMapException("Incorrect inline parameter map format (missmatched name=value pairs): " + token);
×
195
      }
196
    }
1✔
197

198
    if (mapping.getTypeHandler() == null) {
1!
199
      TypeHandler handler;
200
      if (parameterClass == null) {
1✔
201
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
202
      } else {
203
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, mapping.getPropertyName(),
1✔
204
            mapping.getJavaTypeName(), mapping.getJdbcTypeName());
1✔
205
      }
206
      mapping.setTypeHandler(handler);
1✔
207
    }
208

209
    return mapping;
1✔
210
  }
211

212
  /**
213
   * Old parse mapping.
214
   *
215
   * @param token
216
   *          the token
217
   * @param parameterClass
218
   *          the parameter class
219
   * @param typeHandlerFactory
220
   *          the type handler factory
221
   *
222
   * @return the parameter mapping
223
   */
224
  private ParameterMapping oldParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) {
225
    ParameterMapping mapping = new ParameterMapping();
1✔
226
    if (token.indexOf(PARAM_DELIM) > -1) {
1!
227
      StringTokenizer paramParser = new StringTokenizer(token, PARAM_DELIM, true);
1✔
228
      int n1 = paramParser.countTokens();
1✔
229
      if (n1 == 3) {
1✔
230
        String name = paramParser.nextToken();
1✔
231
        paramParser.nextToken(); // ignore ":"
1✔
232
        String type = paramParser.nextToken();
1✔
233
        mapping.setPropertyName(name);
1✔
234
        mapping.setJdbcTypeName(type);
1✔
235
        TypeHandler handler;
236
        if (parameterClass == null) {
1✔
237
          handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
238
        } else {
239
          handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type);
1✔
240
        }
241
        mapping.setTypeHandler(handler);
1✔
242
        return mapping;
1✔
243
      } else if (n1 >= 5) {
1!
244
        String name = paramParser.nextToken();
1✔
245
        paramParser.nextToken(); // ignore ":"
1✔
246
        String type = paramParser.nextToken();
1✔
247
        paramParser.nextToken(); // ignore ":"
1✔
248
        String nullValue = paramParser.nextToken();
1✔
249
        while (paramParser.hasMoreTokens()) {
1!
250
          nullValue = nullValue + paramParser.nextToken();
×
251
        }
252
        mapping.setPropertyName(name);
1✔
253
        mapping.setJdbcTypeName(type);
1✔
254
        mapping.setNullValue(nullValue);
1✔
255
        TypeHandler handler;
256
        if (parameterClass == null) {
1✔
257
          handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
258
        } else {
259
          handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type);
1✔
260
        }
261
        mapping.setTypeHandler(handler);
1✔
262
        return mapping;
1✔
263
      } else {
264
        throw new SqlMapException("Incorrect inline parameter map format: " + token);
×
265
      }
266
    } else {
267
      mapping.setPropertyName(token);
×
268
      TypeHandler handler;
269
      if (parameterClass == null) {
×
270
        handler = typeHandlerFactory.getUnkownTypeHandler();
×
271
      } else {
272
        handler = resolveTypeHandler(typeHandlerFactory, parameterClass, token, null, null);
×
273
      }
274
      mapping.setTypeHandler(handler);
×
275
      return mapping;
×
276
    }
277
  }
278

279
  /**
280
   * Resolve type handler.
281
   *
282
   * @param typeHandlerFactory
283
   *          the type handler factory
284
   * @param clazz
285
   *          the clazz
286
   * @param propertyName
287
   *          the property name
288
   * @param javaType
289
   *          the java type
290
   * @param jdbcType
291
   *          the jdbc type
292
   *
293
   * @return the type handler
294
   */
295
  private TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName,
296
      String javaType, String jdbcType) {
297
    TypeHandler handler = null;
1✔
298
    if (clazz == null) {
1!
299
      // Unknown
300
      handler = typeHandlerFactory.getUnkownTypeHandler();
×
301
    } else if (DomTypeMarker.class.isAssignableFrom(clazz)) {
1✔
302
      // DOM
303
      handler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);
1✔
304
    } else if (java.util.Map.class.isAssignableFrom(clazz)) {
1✔
305
      // Map
306
      if (javaType == null) {
1!
307
        handler = typeHandlerFactory.getUnkownTypeHandler();
1✔
308
        // BUG 1012591 -
309
        // typeHandlerFactory.getTypeHandler(java.lang.Object.class,
310
        // jdbcType);
311
      } else {
312
        try {
313
          javaType = typeHandlerFactory.resolveAlias(javaType);
×
314
          Class javaClass = Resources.classForName(javaType);
×
315
          handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
×
316
        } catch (Exception e) {
×
317
          throw new SqlMapException("Error.  Could not set TypeHandler.  Cause: " + e, e);
×
318
        }
×
319
      }
320
    } else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {
1✔
321
      // Primitive
322
      handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);
1✔
323
    } else {
324
      // JavaBean
325
      if (javaType == null) {
1✔
326

327
        Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);
1✔
328
        handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
1✔
329

330
      } else {
1✔
331
        try {
332
          javaType = typeHandlerFactory.resolveAlias(javaType);
1✔
333
          Class javaClass = Resources.classForName(javaType);
1✔
334
          handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
1✔
335
        } catch (Exception e) {
×
336
          throw new SqlMapException("Error.  Could not set TypeHandler.  Cause: " + e, e);
×
337
        }
1✔
338
      }
339
    }
340
    return handler;
1✔
341
  }
342

343
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc