1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.sqlmap.engine.mapping.sql.dynamic;
17
18 import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
19 import com.ibatis.sqlmap.engine.mapping.parameter.InlineParameterMapParser;
20 import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
21 import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
22 import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
23 import com.ibatis.sqlmap.engine.mapping.sql.Sql;
24 import com.ibatis.sqlmap.engine.mapping.sql.SqlChild;
25 import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
26 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.*;
27 import com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql;
28 import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
29 import com.ibatis.sqlmap.engine.scope.StatementScope;
30
31 import java.io.PrintWriter;
32 import java.io.StringWriter;
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.List;
36
37
38
39
40 public class DynamicSql implements Sql, DynamicParent {
41
42
43 private static final InlineParameterMapParser PARAM_PARSER = new InlineParameterMapParser();
44
45
46 private List children = new ArrayList();
47
48
49 private SqlMapExecutorDelegate delegate;
50
51
52
53
54
55
56
57 public DynamicSql(SqlMapExecutorDelegate delegate) {
58 this.delegate = delegate;
59 }
60
61 public String getSql(StatementScope statementScope, Object parameterObject) {
62 String sql = statementScope.getDynamicSql();
63 if (sql == null) {
64 process(statementScope, parameterObject);
65 sql = statementScope.getDynamicSql();
66 }
67 return sql;
68 }
69
70 public ParameterMap getParameterMap(StatementScope statementScope, Object parameterObject) {
71 ParameterMap map = statementScope.getDynamicParameterMap();
72 if (map == null) {
73 process(statementScope, parameterObject);
74 map = statementScope.getDynamicParameterMap();
75 }
76 return map;
77 }
78
79 public ResultMap getResultMap(StatementScope statementScope, Object parameterObject) {
80 return statementScope.getResultMap();
81 }
82
83 public void cleanup(StatementScope statementScope) {
84 statementScope.setDynamicSql(null);
85 statementScope.setDynamicParameterMap(null);
86 }
87
88
89
90
91
92
93
94
95
96 private void process(StatementScope statementScope, Object parameterObject) {
97 SqlTagContext ctx = new SqlTagContext();
98 List localChildren = children;
99 processBodyChildren(statementScope, ctx, parameterObject, localChildren.iterator());
100
101 ParameterMap map = new ParameterMap(delegate);
102 map.setId(statementScope.getStatement().getId() + "-InlineParameterMap");
103 map.setParameterClass(((MappedStatement) statementScope.getStatement()).getParameterClass());
104 map.setParameterMappingList(ctx.getParameterMappings());
105
106 String dynSql = ctx.getBodyText();
107
108
109 if (SimpleDynamicSql.isSimpleDynamicSql(dynSql)) {
110 dynSql = new SimpleDynamicSql(delegate, dynSql).getSql(statementScope, parameterObject);
111 }
112
113 statementScope.setDynamicSql(dynSql);
114 statementScope.setDynamicParameterMap(map);
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129 private void processBodyChildren(StatementScope statementScope, SqlTagContext ctx, Object parameterObject,
130 Iterator localChildren) {
131 PrintWriter out = ctx.getWriter();
132 processBodyChildren(statementScope, ctx, parameterObject, localChildren, out);
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 private void processBodyChildren(StatementScope statementScope, SqlTagContext ctx, Object parameterObject,
150 Iterator localChildren, PrintWriter out) {
151 while (localChildren.hasNext()) {
152 SqlChild child = (SqlChild) localChildren.next();
153 if (child instanceof SqlText) {
154 SqlText sqlText = (SqlText) child;
155 String sqlStatement = sqlText.getText();
156 if (sqlText.isWhiteSpace()) {
157 out.print(sqlStatement);
158 } else if (!sqlText.isPostParseRequired()) {
159
160
161 out.print(sqlStatement);
162
163 ParameterMapping[] mappings = sqlText.getParameterMappings();
164 if (mappings != null) {
165 for (int i = 0, n = mappings.length; i < n; i++) {
166 ctx.addParameterMapping(mappings[i]);
167 }
168 }
169 } else {
170
171 IterateContext itCtx = ctx.peekIterateContext();
172
173 if (null != itCtx && itCtx.isAllowNext()) {
174 itCtx.next();
175 itCtx.setAllowNext(false);
176 if (!itCtx.hasNext()) {
177 itCtx.setFinal(true);
178 }
179 }
180
181 if (itCtx != null) {
182 StringBuilder sqlStatementBuffer = new StringBuilder(sqlStatement);
183 iteratePropertyReplace(sqlStatementBuffer, itCtx);
184 sqlStatement = sqlStatementBuffer.toString();
185 }
186
187 sqlText = PARAM_PARSER.parseInlineParameterMap(delegate.getTypeHandlerFactory(), sqlStatement);
188
189 ParameterMapping[] mappings = sqlText.getParameterMappings();
190 out.print(sqlText.getText());
191 if (mappings != null) {
192 for (int i = 0, n = mappings.length; i < n; i++) {
193 ctx.addParameterMapping(mappings[i]);
194 }
195 }
196 }
197 } else if (child instanceof SqlTag) {
198 SqlTag tag = (SqlTag) child;
199 SqlTagHandler handler = tag.getHandler();
200 int response = SqlTagHandler.INCLUDE_BODY;
201 do {
202 StringWriter sw = new StringWriter();
203 PrintWriter pw = new PrintWriter(sw);
204
205 response = handler.doStartFragment(ctx, tag, parameterObject);
206 if (response != SqlTagHandler.SKIP_BODY) {
207
208 processBodyChildren(statementScope, ctx, parameterObject, tag.getChildren(), pw);
209 pw.flush();
210 pw.close();
211 StringBuilder body = new StringBuilder(sw.getBuffer());
212 response = handler.doEndFragment(ctx, tag, parameterObject, body);
213 handler.doPrepend(ctx, tag, parameterObject, body);
214
215 if (response != SqlTagHandler.SKIP_BODY) {
216 if (body.length() > 0) {
217 out.print(body.toString());
218 }
219 }
220
221 }
222 } while (response == SqlTagHandler.REPEAT_BODY);
223
224 ctx.popRemoveFirstPrependMarker(tag);
225
226 if (ctx.peekIterateContext() != null && ctx.peekIterateContext().getTag() == tag) {
227 ctx.setAttribute(ctx.peekIterateContext().getTag(), null);
228 ctx.popIterateContext();
229 }
230
231 }
232 }
233 }
234
235
236
237
238
239
240
241
242
243 protected void iteratePropertyReplace(StringBuilder bodyContent, IterateContext iterate) {
244 if (iterate != null) {
245 String[] mappings = new String[] { "#", "$" };
246 for (int i = 0; i < mappings.length; i++) {
247 int startIndex = 0;
248 int endIndex = -1;
249 while (startIndex > -1 && startIndex < bodyContent.length()) {
250 startIndex = bodyContent.indexOf(mappings[i], endIndex + 1);
251 endIndex = bodyContent.indexOf(mappings[i], startIndex + 1);
252 if (startIndex > -1 && endIndex > -1) {
253 bodyContent.replace(startIndex + 1, endIndex,
254 iterate.addIndexToTagProperty(bodyContent.substring(startIndex + 1, endIndex)));
255 }
256 }
257 }
258 }
259 }
260
261
262
263
264
265
266
267
268
269
270
271 protected static void replace(StringBuilder builder, String find, String replace) {
272 int pos = builder.toString().indexOf(find);
273 int len = find.length();
274 while (pos > -1) {
275 builder.replace(pos, pos + len, replace);
276 pos = builder.toString().indexOf(find);
277 }
278 }
279
280 public void addChild(SqlChild child) {
281 children.add(child);
282 }
283
284 }