1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.submitted.language;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.ibatis.builder.BaseBuilder;
23 import org.apache.ibatis.builder.BuilderException;
24 import org.apache.ibatis.builder.ParameterExpression;
25 import org.apache.ibatis.builder.StaticSqlSource;
26 import org.apache.ibatis.mapping.ParameterMapping;
27 import org.apache.ibatis.mapping.SqlSource;
28 import org.apache.ibatis.parsing.GenericTokenParser;
29 import org.apache.ibatis.parsing.TokenHandler;
30 import org.apache.ibatis.reflection.MetaClass;
31 import org.apache.ibatis.session.Configuration;
32 import org.apache.ibatis.type.JdbcType;
33
34
35
36
37 public class VelocitySqlSourceBuilder extends BaseBuilder {
38
39 private static final String parameterProperties = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
40
41 public VelocitySqlSourceBuilder(Configuration configuration) {
42 super(configuration);
43 }
44
45 public SqlSource parse(String originalSql, Class<?> parameterType) {
46 ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType);
47 GenericTokenParser parser = new GenericTokenParser("@{", "}", handler);
48 String sql = parser.parse(originalSql);
49 return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
50 }
51
52 private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
53
54 private final List<ParameterMapping> parameterMappings = new ArrayList<>();
55 private final Class<?> parameterType;
56
57 public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType) {
58 super(configuration);
59 this.parameterType = parameterType;
60 }
61
62 public List<ParameterMapping> getParameterMappings() {
63 return parameterMappings;
64 }
65
66 @Override
67 public String handleToken(String content) {
68 parameterMappings.add(buildParameterMapping(content));
69 return "?";
70 }
71
72 private ParameterMapping buildParameterMapping(String content) {
73 Map<String, String> propertiesMap = parseParameterMapping(content);
74 String property = propertiesMap.get("property");
75 String jdbcType = propertiesMap.get("jdbcType");
76 Class<?> propertyType;
77 if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
78 propertyType = parameterType;
79 } else if (JdbcType.CURSOR.name().equals(jdbcType)) {
80 propertyType = java.sql.ResultSet.class;
81 } else if (property != null) {
82 MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
83 if (metaClass.hasGetter(property)) {
84 propertyType = metaClass.getGetterType(property);
85 } else {
86 propertyType = Object.class;
87 }
88 } else {
89 propertyType = Object.class;
90 }
91 ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
92 if (jdbcType != null) {
93 builder.jdbcType(resolveJdbcType(jdbcType));
94 }
95 Class<?> javaType = null;
96 String typeHandlerAlias = null;
97 for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
98 String name = entry.getKey();
99 String value = entry.getValue();
100 if ("javaType".equals(name)) {
101 javaType = resolveClass(value);
102 builder.javaType(javaType);
103 } else if ("jdbcType".equals(name)) {
104 builder.jdbcType(resolveJdbcType(value));
105 } else if ("mode".equals(name)) {
106 builder.mode(resolveParameterMode(value));
107 } else if ("numericScale".equals(name)) {
108 builder.numericScale(Integer.valueOf(value));
109 } else if ("resultMap".equals(name)) {
110 builder.resultMapId(value);
111 } else if ("typeHandler".equals(name)) {
112 typeHandlerAlias = value;
113 } else if ("jdbcTypeName".equals(name)) {
114 builder.jdbcTypeName(value);
115 } else if ("property".equals(name)) {
116
117 } else if ("expression".equals(name)) {
118 builder.expression(value);
119 } else {
120 throw new BuilderException("An invalid property '" + name + "' was found in mapping @{" + content
121 + "}. Valid properties are " + parameterProperties);
122 }
123 }
124 if (typeHandlerAlias != null) {
125 builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
126 }
127 return builder.build();
128 }
129
130 private Map<String, String> parseParameterMapping(String content) {
131 try {
132 return new ParameterExpression(content);
133 } catch (BuilderException ex) {
134 throw ex;
135 } catch (Exception ex) {
136 throw new BuilderException("Parsing error was found in mapping @{" + content
137 + "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
138 }
139 }
140 }
141
142 }