001: /*
002: * Copyright 2004 Clinton Begin
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.ibatis.sqlmap.engine.mapping.sql.dynamic;
017:
018: import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
019: import com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMap;
020: import com.ibatis.sqlmap.engine.mapping.parameter.InlineParameterMapParser;
021: import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
022: import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
023: import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
024: import com.ibatis.sqlmap.engine.mapping.sql.Sql;
025: import com.ibatis.sqlmap.engine.mapping.sql.SqlChild;
026: import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
027: import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.*;
028: import com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql;
029: import com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement;
030: import com.ibatis.sqlmap.engine.scope.RequestScope;
031:
032: import java.io.PrintWriter;
033: import java.io.StringWriter;
034: import java.util.ArrayList;
035: import java.util.Iterator;
036: import java.util.List;
037:
038: public class DynamicSql implements Sql, DynamicParent {
039:
040: private static final InlineParameterMapParser PARAM_PARSER = new InlineParameterMapParser();
041:
042: private List children = new ArrayList();
043: private SqlMapExecutorDelegate delegate;
044:
045: public DynamicSql(SqlMapExecutorDelegate delegate) {
046: this .delegate = delegate;
047: }
048:
049: public String getSql(RequestScope request, Object parameterObject) {
050: String sql = request.getDynamicSql();
051: if (sql == null) {
052: process(request, parameterObject);
053: sql = request.getDynamicSql();
054: }
055: return sql;
056: }
057:
058: public ParameterMap getParameterMap(RequestScope request,
059: Object parameterObject) {
060: ParameterMap map = request.getDynamicParameterMap();
061: if (map == null) {
062: process(request, parameterObject);
063: map = request.getDynamicParameterMap();
064: }
065: return map;
066: }
067:
068: public ResultMap getResultMap(RequestScope request,
069: Object parameterObject) {
070: return request.getResultMap();
071: }
072:
073: public void cleanup(RequestScope request) {
074: request.setDynamicSql(null);
075: request.setDynamicParameterMap(null);
076: }
077:
078: private void process(RequestScope request, Object parameterObject) {
079: SqlTagContext ctx = new SqlTagContext();
080: List localChildren = children;
081: processBodyChildren(request, ctx, parameterObject,
082: localChildren.iterator());
083:
084: BasicParameterMap map = new BasicParameterMap(delegate);
085: map.setId(request.getStatement().getId()
086: + "-InlineParameterMap");
087: map.setParameterClass(((GeneralStatement) request
088: .getStatement()).getParameterClass());
089: map.setParameterMappingList(ctx.getParameterMappings());
090:
091: String dynSql = ctx.getBodyText();
092:
093: // Processes $substitutions$ after DynamicSql
094: if (SimpleDynamicSql.isSimpleDynamicSql(dynSql)) {
095: dynSql = new SimpleDynamicSql(delegate, dynSql).getSql(
096: request, parameterObject);
097: }
098:
099: request.setDynamicSql(dynSql);
100: request.setDynamicParameterMap(map);
101: }
102:
103: private void processBodyChildren(RequestScope request,
104: SqlTagContext ctx, Object parameterObject,
105: Iterator localChildren) {
106: PrintWriter out = ctx.getWriter();
107: processBodyChildren(request, ctx, parameterObject,
108: localChildren, out);
109: }
110:
111: private void processBodyChildren(RequestScope request,
112: SqlTagContext ctx, Object parameterObject,
113: Iterator localChildren, PrintWriter out) {
114: while (localChildren.hasNext()) {
115: SqlChild child = (SqlChild) localChildren.next();
116: if (child instanceof SqlText) {
117: SqlText sqlText = (SqlText) child;
118: String sqlStatement = sqlText.getText();
119: if (sqlText.isWhiteSpace()) {
120: out.print(sqlStatement);
121: } else if (!sqlText.isPostParseRequired()) {
122:
123: // BODY OUT
124: out.print(sqlStatement);
125:
126: ParameterMapping[] mappings = sqlText
127: .getParameterMappings();
128: if (mappings != null) {
129: for (int i = 0, n = mappings.length; i < n; i++) {
130: ctx.addParameterMapping(mappings[i]);
131: }
132: }
133: } else {
134:
135: IterateContext itCtx = ctx.peekIterateContext();
136:
137: if (null != itCtx && itCtx.isAllowNext()) {
138: itCtx.next();
139: itCtx.setAllowNext(false);
140: if (!itCtx.hasNext()) {
141: itCtx.setFinal(true);
142: }
143: }
144:
145: if (itCtx != null) {
146: StringBuffer sqlStatementBuffer = new StringBuffer(
147: sqlStatement);
148: iteratePropertyReplace(sqlStatementBuffer,
149: itCtx);
150: sqlStatement = sqlStatementBuffer.toString();
151: }
152:
153: sqlText = PARAM_PARSER.parseInlineParameterMap(
154: delegate.getTypeHandlerFactory(),
155: sqlStatement);
156:
157: ParameterMapping[] mappings = sqlText
158: .getParameterMappings();
159: out.print(sqlText.getText());
160: if (mappings != null) {
161: for (int i = 0, n = mappings.length; i < n; i++) {
162: ctx.addParameterMapping(mappings[i]);
163: }
164: }
165: }
166: } else if (child instanceof SqlTag) {
167: SqlTag tag = (SqlTag) child;
168: SqlTagHandler handler = tag.getHandler();
169: int response = SqlTagHandler.INCLUDE_BODY;
170: do {
171: StringWriter sw = new StringWriter();
172: PrintWriter pw = new PrintWriter(sw);
173:
174: response = handler.doStartFragment(ctx, tag,
175: parameterObject);
176: if (response != SqlTagHandler.SKIP_BODY) {
177:
178: processBodyChildren(request, ctx,
179: parameterObject, tag.getChildren(), pw);
180: pw.flush();
181: pw.close();
182: StringBuffer body = sw.getBuffer();
183: response = handler.doEndFragment(ctx, tag,
184: parameterObject, body);
185: handler.doPrepend(ctx, tag, parameterObject,
186: body);
187:
188: if (response != SqlTagHandler.SKIP_BODY) {
189: if (body.length() > 0) {
190: out.print(body.toString());
191: }
192: }
193:
194: }
195: } while (response == SqlTagHandler.REPEAT_BODY);
196:
197: ctx.popRemoveFirstPrependMarker(tag);
198:
199: if (ctx.peekIterateContext() != null
200: && ctx.peekIterateContext().getTag() == tag) {
201: ctx.setAttribute(ctx.peekIterateContext().getTag(),
202: null);
203: ctx.popIterateContext();
204: }
205:
206: }
207: }
208: }
209:
210: /**
211: *
212: * @param bodyContent
213: * @param iterate
214: */
215: protected void iteratePropertyReplace(StringBuffer bodyContent,
216: IterateContext iterate) {
217: if (iterate != null) {
218: String[] mappings = new String[] { "#", "$" };
219: for (int i = 0; i < mappings.length; i++) {
220: int startIndex = 0;
221: int endIndex = -1;
222: while (startIndex > -1
223: && startIndex < bodyContent.length()) {
224: startIndex = bodyContent.indexOf(mappings[i],
225: endIndex + 1);
226: endIndex = bodyContent.indexOf(mappings[i],
227: startIndex + 1);
228: if (startIndex > -1 && endIndex > -1) {
229: bodyContent
230: .replace(
231: startIndex + 1,
232: endIndex,
233: iterate
234: .addIndexToTagProperty(bodyContent
235: .substring(
236: startIndex + 1,
237: endIndex)));
238: }
239: }
240: }
241: }
242: }
243:
244: protected static void replace(StringBuffer buffer, String find,
245: String replace) {
246: int pos = buffer.toString().indexOf(find);
247: int len = find.length();
248: while (pos > -1) {
249: buffer.replace(pos, pos + len, replace);
250: pos = buffer.toString().indexOf(find);
251: }
252: }
253:
254: public void addChild(SqlChild child) {
255: children.add(child);
256: }
257:
258: }
|