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

mybatis / ibatis-2 / #341

08 Sep 2023 11:16PM UTC coverage: 64.938% (+0.03%) from 64.913%
#341

push

github

web-flow
Merge pull request #183 from hazendaz/master

fixes #174, update GHA, maven wrapper, fix EOL markers, do not use star imports

5047 of 7772 relevant lines covered (64.94%)

0.65 hits per line

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

88.49
/src/main/java/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java
1
/*
2
 * Copyright 2004-2023 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.builder.xml;
17

18
import com.ibatis.common.resources.Resources;
19
import com.ibatis.common.xml.Nodelet;
20
import com.ibatis.common.xml.NodeletException;
21
import com.ibatis.common.xml.NodeletParser;
22
import com.ibatis.common.xml.NodeletUtils;
23
import com.ibatis.sqlmap.client.SqlMapException;
24
import com.ibatis.sqlmap.engine.cache.CacheController;
25
import com.ibatis.sqlmap.engine.config.CacheModelConfig;
26
import com.ibatis.sqlmap.engine.config.ParameterMapConfig;
27
import com.ibatis.sqlmap.engine.config.ResultMapConfig;
28
import com.ibatis.sqlmap.engine.mapping.statement.*;
29

30
import java.io.InputStream;
31
import java.io.Reader;
32
import java.util.Properties;
33

34
import org.w3c.dom.Node;
35

36
/**
37
 * The Class SqlMapParser.
38
 */
39
public class SqlMapParser {
40

41
  /** The parser. */
42
  private final NodeletParser parser;
43

44
  /** The state. */
45
  private XmlParserState state;
46

47
  /** The statement parser. */
48
  private SqlStatementParser statementParser;
49

50
  /**
51
   * Instantiates a new sql map parser.
52
   *
53
   * @param state
54
   *          the state
55
   */
56
  public SqlMapParser(XmlParserState state) {
1✔
57
    this.parser = new NodeletParser();
1✔
58
    this.state = state;
1✔
59

60
    parser.setValidation(true);
1✔
61
    parser.setEntityResolver(new SqlMapClasspathEntityResolver());
1✔
62

63
    statementParser = new SqlStatementParser(this.state);
1✔
64

65
    addSqlMapNodelets();
1✔
66
    addSqlNodelets();
1✔
67
    addTypeAliasNodelets();
1✔
68
    addCacheModelNodelets();
1✔
69
    addParameterMapNodelets();
1✔
70
    addResultMapNodelets();
1✔
71
    addStatementNodelets();
1✔
72

73
  }
1✔
74

75
  /**
76
   * Parses the.
77
   *
78
   * @param reader
79
   *          the reader
80
   *
81
   * @throws NodeletException
82
   *           the nodelet exception
83
   */
84
  public void parse(Reader reader) throws NodeletException {
85
    parser.parse(reader);
1✔
86
  }
1✔
87

88
  /**
89
   * Parses the.
90
   *
91
   * @param inputStream
92
   *          the input stream
93
   *
94
   * @throws NodeletException
95
   *           the nodelet exception
96
   */
97
  public void parse(InputStream inputStream) throws NodeletException {
98
    parser.parse(inputStream);
×
99
  }
×
100

101
  /**
102
   * Adds the sql map nodelets.
103
   */
104
  private void addSqlMapNodelets() {
105
    parser.addNodelet("/sqlMap", new Nodelet() {
1✔
106
      public void process(Node node) throws Exception {
107
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
108
        state.setNamespace(attributes.getProperty("namespace"));
1✔
109
      }
1✔
110
    });
111
  }
1✔
112

113
  /**
114
   * Adds the sql nodelets.
115
   */
116
  private void addSqlNodelets() {
117
    parser.addNodelet("/sqlMap/sql", new Nodelet() {
1✔
118
      public void process(Node node) throws Exception {
119
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
120
        String id = attributes.getProperty("id");
1✔
121
        if (state.isUseStatementNamespaces()) {
1✔
122
          id = state.applyNamespace(id);
×
123
        }
124
        if (state.getSqlIncludes().containsKey(id)) {
1✔
125
          throw new SqlMapException("Duplicate <sql>-include '" + id + "' found.");
×
126
        } else {
127
          state.getSqlIncludes().put(id, node);
1✔
128
        }
129
      }
1✔
130
    });
131
  }
1✔
132

133
  /**
134
   * Adds the type alias nodelets.
135
   */
136
  private void addTypeAliasNodelets() {
137
    parser.addNodelet("/sqlMap/typeAlias", new Nodelet() {
1✔
138
      public void process(Node node) throws Exception {
139
        Properties prop = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
140
        String alias = prop.getProperty("alias");
1✔
141
        String type = prop.getProperty("type");
1✔
142
        state.getConfig().getTypeHandlerFactory().putTypeAlias(alias, type);
1✔
143
      }
1✔
144
    });
145
  }
1✔
146

147
  /**
148
   * Adds the cache model nodelets.
149
   */
150
  private void addCacheModelNodelets() {
151
    parser.addNodelet("/sqlMap/cacheModel", new Nodelet() {
1✔
152
      public void process(Node node) throws Exception {
153
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
154
        String id = state.applyNamespace(attributes.getProperty("id"));
1✔
155
        String type = attributes.getProperty("type");
1✔
156
        String readOnlyAttr = attributes.getProperty("readOnly");
1✔
157
        Boolean readOnly = readOnlyAttr == null || readOnlyAttr.length() <= 0 ? null
1✔
158
            : new Boolean("true".equals(readOnlyAttr));
1✔
159
        String serializeAttr = attributes.getProperty("serialize");
1✔
160
        Boolean serialize = serializeAttr == null || serializeAttr.length() <= 0 ? null
1✔
161
            : new Boolean("true".equals(serializeAttr));
1✔
162
        type = state.getConfig().getTypeHandlerFactory().resolveAlias(type);
1✔
163
        Class clazz = Resources.classForName(type);
1✔
164
        if (readOnly == null) {
1✔
165
          readOnly = Boolean.TRUE;
1✔
166
        }
167
        if (serialize == null) {
1✔
168
          serialize = Boolean.FALSE;
1✔
169
        }
170
        CacheModelConfig cacheConfig = state.getConfig().newCacheModelConfig(id,
1✔
171
            (CacheController) Resources.instantiate(clazz), readOnly.booleanValue(), serialize.booleanValue());
1✔
172
        state.setCacheConfig(cacheConfig);
1✔
173
      }
1✔
174
    });
175
    parser.addNodelet("/sqlMap/cacheModel/end()", new Nodelet() {
1✔
176
      public void process(Node node) throws Exception {
177
        state.getCacheConfig().setControllerProperties(state.getCacheProps());
1✔
178
      }
1✔
179
    });
180
    parser.addNodelet("/sqlMap/cacheModel/property", new Nodelet() {
1✔
181
      public void process(Node node) throws Exception {
182
        state.getConfig().getErrorContext().setMoreInfo("Check the cache model properties.");
1✔
183
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
184
        String name = attributes.getProperty("name");
1✔
185
        String value = NodeletUtils.parsePropertyTokens(attributes.getProperty("value"), state.getGlobalProps());
1✔
186
        state.getCacheProps().setProperty(name, value);
1✔
187
      }
1✔
188
    });
189
    parser.addNodelet("/sqlMap/cacheModel/flushOnExecute", new Nodelet() {
1✔
190
      public void process(Node node) throws Exception {
191
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
192
        String statement = childAttributes.getProperty("statement");
1✔
193
        state.getCacheConfig().addFlushTriggerStatement(statement);
1✔
194
      }
1✔
195
    });
196
    parser.addNodelet("/sqlMap/cacheModel/flushInterval", new Nodelet() {
1✔
197
      public void process(Node node) throws Exception {
198
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
199
        try {
200
          int milliseconds = childAttributes.getProperty("milliseconds") == null ? 0
1✔
201
              : Integer.parseInt(childAttributes.getProperty("milliseconds"));
1✔
202
          int seconds = childAttributes.getProperty("seconds") == null ? 0
1✔
203
              : Integer.parseInt(childAttributes.getProperty("seconds"));
1✔
204
          int minutes = childAttributes.getProperty("minutes") == null ? 0
1✔
205
              : Integer.parseInt(childAttributes.getProperty("minutes"));
1✔
206
          int hours = childAttributes.getProperty("hours") == null ? 0
1✔
207
              : Integer.parseInt(childAttributes.getProperty("hours"));
1✔
208
          state.getCacheConfig().setFlushInterval(hours, minutes, seconds, milliseconds);
1✔
209
        } catch (NumberFormatException e) {
×
210
          throw new RuntimeException("Error building cache in '" + "resourceNAME"
×
211
              + "'.  Flush interval milliseconds must be a valid long integer value.  Cause: " + e, e);
212
        }
1✔
213
      }
1✔
214
    });
215
  }
1✔
216

217
  /**
218
   * Adds the parameter map nodelets.
219
   */
220
  private void addParameterMapNodelets() {
221
    parser.addNodelet("/sqlMap/parameterMap/end()", new Nodelet() {
1✔
222
      public void process(Node node) throws Exception {
223
        state.getConfig().getErrorContext().setMoreInfo(null);
1✔
224
        state.getConfig().getErrorContext().setObjectId(null);
1✔
225
        state.setParamConfig(null);
1✔
226
      }
1✔
227
    });
228
    parser.addNodelet("/sqlMap/parameterMap", new Nodelet() {
1✔
229
      public void process(Node node) throws Exception {
230
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
231
        String id = state.applyNamespace(attributes.getProperty("id"));
1✔
232
        String parameterClassName = attributes.getProperty("class");
1✔
233
        parameterClassName = state.getConfig().getTypeHandlerFactory().resolveAlias(parameterClassName);
1✔
234
        try {
235
          state.getConfig().getErrorContext().setMoreInfo("Check the parameter class.");
1✔
236
          ParameterMapConfig paramConf = state.getConfig().newParameterMapConfig(id,
1✔
237
              Resources.classForName(parameterClassName));
1✔
238
          state.setParamConfig(paramConf);
1✔
239
        } catch (Exception e) {
×
240
          throw new SqlMapException("Error configuring ParameterMap.  Could not set ParameterClass.  Cause: " + e, e);
×
241
        }
1✔
242
      }
1✔
243
    });
244
    parser.addNodelet("/sqlMap/parameterMap/parameter", new Nodelet() {
1✔
245
      public void process(Node node) throws Exception {
246
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
247
        String propertyName = childAttributes.getProperty("property");
1✔
248
        String jdbcType = childAttributes.getProperty("jdbcType");
1✔
249
        String type = childAttributes.getProperty("typeName");
1✔
250
        String javaType = childAttributes.getProperty("javaType");
1✔
251
        String resultMap = state.applyNamespace(childAttributes.getProperty("resultMap"));
1✔
252
        String nullValue = childAttributes.getProperty("nullValue");
1✔
253
        String mode = childAttributes.getProperty("mode");
1✔
254
        String callback = childAttributes.getProperty("typeHandler");
1✔
255
        String numericScaleProp = childAttributes.getProperty("numericScale");
1✔
256

257
        callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
1✔
258
        Object typeHandlerImpl = null;
1✔
259
        if (callback != null) {
1✔
260
          typeHandlerImpl = Resources.instantiate(callback);
1✔
261
        }
262

263
        javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
1✔
264
        Class javaClass = null;
1✔
265
        try {
266
          if (javaType != null && javaType.length() > 0) {
1✔
267
            javaClass = Resources.classForName(javaType);
1✔
268
          }
269
        } catch (ClassNotFoundException e) {
×
270
          throw new RuntimeException("Error setting javaType on parameter mapping.  Cause: " + e);
×
271
        }
1✔
272

273
        Integer numericScale = null;
1✔
274
        if (numericScaleProp != null) {
1✔
275
          numericScale = Integer.valueOf(numericScaleProp);
×
276
        }
277

278
        state.getParamConfig().addParameterMapping(propertyName, javaClass, jdbcType, nullValue, mode, type,
1✔
279
            numericScale, typeHandlerImpl, resultMap);
280
      }
1✔
281
    });
282
  }
1✔
283

284
  /**
285
   * Adds the result map nodelets.
286
   */
287
  private void addResultMapNodelets() {
288
    parser.addNodelet("/sqlMap/resultMap/end()", new Nodelet() {
1✔
289
      public void process(Node node) throws Exception {
290
        state.getConfig().getErrorContext().setMoreInfo(null);
1✔
291
        state.getConfig().getErrorContext().setObjectId(null);
1✔
292
      }
1✔
293
    });
294
    parser.addNodelet("/sqlMap/resultMap", new Nodelet() {
1✔
295
      public void process(Node node) throws Exception {
296
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
297
        String id = state.applyNamespace(attributes.getProperty("id"));
1✔
298
        String resultClassName = attributes.getProperty("class");
1✔
299
        String extended = state.applyNamespace(attributes.getProperty("extends"));
1✔
300
        String xmlName = attributes.getProperty("xmlName");
1✔
301
        String groupBy = attributes.getProperty("groupBy");
1✔
302

303
        resultClassName = state.getConfig().getTypeHandlerFactory().resolveAlias(resultClassName);
1✔
304
        Class resultClass;
305
        try {
306
          state.getConfig().getErrorContext().setMoreInfo("Check the result class.");
1✔
307
          resultClass = Resources.classForName(resultClassName);
1✔
308
        } catch (Exception e) {
×
309
          throw new RuntimeException("Error configuring Result.  Could not set ResultClass.  Cause: " + e, e);
×
310
        }
1✔
311
        ResultMapConfig resultConf = state.getConfig().newResultMapConfig(id, resultClass, groupBy, extended, xmlName);
1✔
312
        state.setResultConfig(resultConf);
1✔
313
      }
1✔
314
    });
315
    parser.addNodelet("/sqlMap/resultMap/result", new Nodelet() {
1✔
316
      public void process(Node node) throws Exception {
317
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
318
        String propertyName = childAttributes.getProperty("property");
1✔
319
        String nullValue = childAttributes.getProperty("nullValue");
1✔
320
        String jdbcType = childAttributes.getProperty("jdbcType");
1✔
321
        String javaType = childAttributes.getProperty("javaType");
1✔
322
        String columnName = childAttributes.getProperty("column");
1✔
323
        String columnIndexProp = childAttributes.getProperty("columnIndex");
1✔
324
        String statementName = childAttributes.getProperty("select");
1✔
325
        String resultMapName = childAttributes.getProperty("resultMap");
1✔
326
        String callback = childAttributes.getProperty("typeHandler");
1✔
327
        String notNullColumn = childAttributes.getProperty("notNullColumn");
1✔
328

329
        state.getConfig().getErrorContext().setMoreInfo("Check the result mapping property type or name.");
1✔
330
        Class javaClass = null;
1✔
331
        try {
332
          javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
1✔
333
          if (javaType != null && javaType.length() > 0) {
1✔
334
            javaClass = Resources.classForName(javaType);
1✔
335
          }
336
        } catch (ClassNotFoundException e) {
×
337
          throw new RuntimeException("Error setting java type on result discriminator mapping.  Cause: " + e);
×
338
        }
1✔
339

340
        state.getConfig().getErrorContext().setMoreInfo("Check the result mapping typeHandler attribute '" + callback
1✔
341
            + "' (must be a TypeHandler or TypeHandlerCallback implementation).");
342
        Object typeHandlerImpl = null;
1✔
343
        try {
344
          if (callback != null && callback.length() > 0) {
1✔
345
            callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
1✔
346
            typeHandlerImpl = Resources.instantiate(callback);
1✔
347
          }
348
        } catch (Exception e) {
×
349
          throw new RuntimeException("Error occurred during custom type handler configuration.  Cause: " + e, e);
×
350
        }
1✔
351

352
        Integer columnIndex = null;
1✔
353
        if (columnIndexProp != null) {
1✔
354
          try {
355
            columnIndex = Integer.valueOf(columnIndexProp);
1✔
356
          } catch (Exception e) {
×
357
            throw new RuntimeException("Error parsing column index.  Cause: " + e, e);
×
358
          }
1✔
359
        }
360

361
        state.getResultConfig().addResultMapping(propertyName, columnName, columnIndex, javaClass, jdbcType, nullValue,
1✔
362
            notNullColumn, statementName, resultMapName, typeHandlerImpl);
363
      }
1✔
364
    });
365

366
    parser.addNodelet("/sqlMap/resultMap/discriminator/subMap", new Nodelet() {
1✔
367
      public void process(Node node) throws Exception {
368
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
369
        String value = childAttributes.getProperty("value");
1✔
370
        String resultMap = childAttributes.getProperty("resultMap");
1✔
371
        resultMap = state.applyNamespace(resultMap);
1✔
372
        state.getResultConfig().addDiscriminatorSubMap(value, resultMap);
1✔
373
      }
1✔
374
    });
375

376
    parser.addNodelet("/sqlMap/resultMap/discriminator", new Nodelet() {
1✔
377
      public void process(Node node) throws Exception {
378
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
1✔
379
        String nullValue = childAttributes.getProperty("nullValue");
1✔
380
        String jdbcType = childAttributes.getProperty("jdbcType");
1✔
381
        String javaType = childAttributes.getProperty("javaType");
1✔
382
        String columnName = childAttributes.getProperty("column");
1✔
383
        String columnIndexProp = childAttributes.getProperty("columnIndex");
1✔
384
        String callback = childAttributes.getProperty("typeHandler");
1✔
385

386
        state.getConfig().getErrorContext().setMoreInfo("Check the disriminator type or name.");
1✔
387
        Class javaClass = null;
1✔
388
        try {
389
          javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
1✔
390
          if (javaType != null && javaType.length() > 0) {
1✔
391
            javaClass = Resources.classForName(javaType);
1✔
392
          }
393
        } catch (ClassNotFoundException e) {
×
394
          throw new RuntimeException("Error setting java type on result discriminator mapping.  Cause: " + e);
×
395
        }
1✔
396

397
        state.getConfig().getErrorContext().setMoreInfo("Check the result mapping discriminator typeHandler attribute '"
1✔
398
            + callback + "' (must be a TypeHandlerCallback implementation).");
399
        Object typeHandlerImpl = null;
1✔
400
        try {
401
          if (callback != null && callback.length() > 0) {
1✔
402
            callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
×
403
            typeHandlerImpl = Resources.instantiate(callback);
×
404
          }
405
        } catch (Exception e) {
×
406
          throw new RuntimeException("Error occurred during custom type handler configuration.  Cause: " + e, e);
×
407
        }
1✔
408

409
        Integer columnIndex = null;
1✔
410
        if (columnIndexProp != null) {
1✔
411
          try {
412
            columnIndex = Integer.valueOf(columnIndexProp);
×
413
          } catch (Exception e) {
×
414
            throw new RuntimeException("Error parsing column index.  Cause: " + e, e);
×
415
          }
×
416
        }
417

418
        state.getResultConfig().setDiscriminator(columnName, columnIndex, javaClass, jdbcType, nullValue,
1✔
419
            typeHandlerImpl);
420
      }
1✔
421
    });
422
  }
1✔
423

424
  /**
425
   * Adds the statement nodelets.
426
   */
427
  protected void addStatementNodelets() {
428
    parser.addNodelet("/sqlMap/statement", new Nodelet() {
1✔
429
      public void process(Node node) throws Exception {
430
        statementParser.parseGeneralStatement(node, new MappedStatement());
1✔
431
      }
1✔
432
    });
433
    parser.addNodelet("/sqlMap/insert", new Nodelet() {
1✔
434
      public void process(Node node) throws Exception {
435
        statementParser.parseGeneralStatement(node, new InsertStatement());
1✔
436
      }
1✔
437
    });
438
    parser.addNodelet("/sqlMap/update", new Nodelet() {
1✔
439
      public void process(Node node) throws Exception {
440
        statementParser.parseGeneralStatement(node, new UpdateStatement());
1✔
441
      }
1✔
442
    });
443
    parser.addNodelet("/sqlMap/delete", new Nodelet() {
1✔
444
      public void process(Node node) throws Exception {
445
        statementParser.parseGeneralStatement(node, new DeleteStatement());
1✔
446
      }
1✔
447
    });
448
    parser.addNodelet("/sqlMap/select", new Nodelet() {
1✔
449
      public void process(Node node) throws Exception {
450
        statementParser.parseGeneralStatement(node, new SelectStatement());
1✔
451
      }
1✔
452
    });
453
    parser.addNodelet("/sqlMap/procedure", new Nodelet() {
1✔
454
      public void process(Node node) throws Exception {
455
        statementParser.parseGeneralStatement(node, new ProcedureStatement());
1✔
456
      }
1✔
457
    });
458
  }
1✔
459

460
}
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