KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibatis > sqlmap > engine > builder > xml > SqlStatementParser


1 package com.ibatis.sqlmap.engine.builder.xml;
2
3 import java.sql.ResultSet JavaDoc;
4 import java.util.Arrays JavaDoc;
5 import java.util.List JavaDoc;
6 import java.util.Properties JavaDoc;
7
8 import org.w3c.dom.CharacterData JavaDoc;
9 import org.w3c.dom.Node JavaDoc;
10 import org.w3c.dom.NodeList JavaDoc;
11
12 import com.ibatis.common.beans.Probe;
13 import com.ibatis.common.beans.ProbeFactory;
14 import com.ibatis.common.exception.NestedRuntimeException;
15 import com.ibatis.common.resources.Resources;
16 import com.ibatis.common.xml.NodeletUtils;
17 import com.ibatis.sqlmap.client.SqlMapException;
18 import com.ibatis.sqlmap.engine.cache.CacheModel;
19 import com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMap;
20 import com.ibatis.sqlmap.engine.mapping.parameter.InlineParameterMapParser;
21 import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
22 import com.ibatis.sqlmap.engine.mapping.result.AutoResultMap;
23 import com.ibatis.sqlmap.engine.mapping.result.BasicResultMap;
24 import com.ibatis.sqlmap.engine.mapping.sql.Sql;
25 import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
26 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSql;
27 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.DynamicParent;
28 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.DynamicTagHandler;
29 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.IterateTagHandler;
30 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.SqlTag;
31 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.SqlTagHandler;
32 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.SqlTagHandlerFactory;
33 import com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql;
34 import com.ibatis.sqlmap.engine.mapping.sql.stat.StaticSql;
35 import com.ibatis.sqlmap.engine.mapping.statement.CachingStatement;
36 import com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement;
37 import com.ibatis.sqlmap.engine.mapping.statement.InsertStatement;
38 import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
39 import com.ibatis.sqlmap.engine.mapping.statement.SelectKeyStatement;
40
41 public class SqlStatementParser extends BaseParser {
42
43   private static final Probe PROBE = ProbeFactory.getProbe();
44
45   private static final InlineParameterMapParser PARAM_PARSER = new InlineParameterMapParser();
46
47   public SqlStatementParser(Variables vars) {
48     super(vars);
49   }
50
51   public MappedStatement parseGeneralStatement(Node JavaDoc node, GeneralStatement statement) {
52     vars.errorCtx.setActivity("parsing a mapped statement");
53
54     // get attributes
55
Properties JavaDoc attributes = NodeletUtils.parseAttributes(node, vars.currentProperties);
56     String JavaDoc id = attributes.getProperty("id");
57
58     if (vars.useStatementNamespaces) {
59       id = applyNamespace(id);
60     }
61
62     String JavaDoc parameterMapName = applyNamespace(attributes.getProperty("parameterMap"));
63     String JavaDoc parameterClassName = attributes.getProperty("parameterClass");
64     String JavaDoc resultMapName = applyNamespace(attributes.getProperty("resultMap"));
65     String JavaDoc resultClassName = attributes.getProperty("resultClass");
66     String JavaDoc cacheModelName = applyNamespace(attributes.getProperty("cacheModel"));
67     String JavaDoc xmlResultName = attributes.getProperty("xmlResultName");
68     String JavaDoc resultSetType = attributes.getProperty("resultSetType");
69     String JavaDoc fetchSize = attributes.getProperty("fetchSize");
70     String JavaDoc allowRemapping = attributes.getProperty("remapResults");
71
72     vars.errorCtx.setObjectId(id + " statement");
73
74     parameterClassName = vars.typeHandlerFactory.resolveAlias(parameterClassName);
75     resultClassName = vars.typeHandlerFactory.resolveAlias(resultClassName);
76
77     Class JavaDoc parameterClass = null;
78     Class JavaDoc resultClass = null;
79
80     // get parameter and result maps
81

82     vars.errorCtx.setMoreInfo("Check the result map name.");
83     BasicResultMap resultMap = null;
84     if (resultMapName != null) {
85       resultMap = (BasicResultMap) vars.client.getDelegate().getResultMap(resultMapName);
86     }
87
88     vars.errorCtx.setMoreInfo("Check the parameter map name.");
89     BasicParameterMap parameterMap = null;
90     if (parameterMapName != null) {
91       parameterMap = (BasicParameterMap) vars.client.getDelegate().getParameterMap(parameterMapName);
92     }
93
94     statement.setId(id);
95     statement.setParameterMap(parameterMap);
96     statement.setResultMap(resultMap);
97     statement.setResource(vars.errorCtx.getResource());
98
99     if (resultSetType != null) {
100       if ("FORWARD_ONLY".equals(resultSetType)) {
101         statement.setResultSetType(new Integer JavaDoc(ResultSet.TYPE_FORWARD_ONLY));
102       } else if ("SCROLL_INSENSITIVE".equals(resultSetType)) {
103         statement.setResultSetType(new Integer JavaDoc(ResultSet.TYPE_SCROLL_INSENSITIVE));
104       } else if ("SCROLL_SENSITIVE".equals(resultSetType)) {
105         statement.setResultSetType(new Integer JavaDoc(ResultSet.TYPE_SCROLL_SENSITIVE));
106       }
107     }
108
109     if (fetchSize != null) {
110       statement.setFetchSize(new Integer JavaDoc(fetchSize));
111     }
112
113     // set parameter class either from attribute or from map (make sure to match)
114
if (parameterMap == null) {
115       try {
116         if (parameterClassName != null) {
117           vars.errorCtx.setMoreInfo("Check the parameter class.");
118           parameterClass = Resources.classForName(parameterClassName);
119           statement.setParameterClass(parameterClass);
120         }
121       } catch (ClassNotFoundException JavaDoc e) {
122         throw new SqlMapException("Error. Could not set parameter class. Cause: " + e, e);
123       }
124     } else {
125       statement.setParameterClass(parameterMap.getParameterClass());
126     }
127
128     try {
129       if (resultClassName != null) {
130         vars.errorCtx.setMoreInfo("Check the result class.");
131         resultClass = Resources.classForName(resultClassName);
132       }
133     } catch (ClassNotFoundException JavaDoc e) {
134       throw new SqlMapException("Error. Could not set result class. Cause: " + e, e);
135     }
136
137     // process SQL statement, including inline parameter maps
138
vars.errorCtx.setMoreInfo("Check the SQL statement.");
139     processSqlStatement(node, statement);
140
141     // set up either null result map or automatic result mapping
142
if (resultMap == null && resultClass == null) {
143       statement.setResultMap(null);
144     } else if (resultMap == null) {
145       resultMap = new AutoResultMap(vars.client.getDelegate(), "true".equals(allowRemapping));
146       resultMap.setId(statement.getId() + "-AutoResultMap");
147       resultMap.setResultClass(resultClass);
148       resultMap.setXmlName(xmlResultName);
149       resultMap.setResource(statement.getResource());
150       statement.setResultMap(resultMap);
151
152     }
153
154     vars.errorCtx.setMoreInfo(null);
155     vars.errorCtx.setObjectId(null);
156
157     statement.setSqlMapClient(vars.client);
158     if (cacheModelName != null && cacheModelName.length() > 0 && vars.client.getDelegate().isCacheModelsEnabled()) {
159       CacheModel cacheModel = vars.client.getDelegate().getCacheModel(cacheModelName);
160       return new CachingStatement(statement, cacheModel);
161     } else {
162       return statement;
163     }
164
165   }
166
167   private void processSqlStatement(Node JavaDoc n, GeneralStatement statement) {
168     vars.errorCtx.setActivity("processing an SQL statement");
169
170     boolean isDynamic = false;
171     DynamicSql dynamic = new DynamicSql(vars.client.getDelegate());
172     StringBuffer JavaDoc sqlBuffer = new StringBuffer JavaDoc();
173
174     isDynamic = parseDynamicTags(n, dynamic, sqlBuffer, isDynamic, false);
175     if (statement instanceof InsertStatement) {
176       InsertStatement insertStatement = ((InsertStatement) statement);
177       SelectKeyStatement selectKeyStatement = findAndParseSelectKeyStatement(n, statement);
178       insertStatement.setSelectKeyStatement(selectKeyStatement);
179     }
180
181     String JavaDoc sqlStatement = sqlBuffer.toString();
182     if (isDynamic) {
183       statement.setSql(dynamic);
184     } else {
185       applyInlineParameterMap(statement, sqlStatement);
186     }
187
188   }
189
190   private boolean parseDynamicTags(Node JavaDoc node, DynamicParent dynamic, StringBuffer JavaDoc sqlBuffer, boolean isDynamic, boolean postParseRequired) {
191     vars.errorCtx.setActivity("parsing dynamic SQL tags");
192
193     NodeList JavaDoc children = node.getChildNodes();
194     for (int i = 0; i < children.getLength(); i++) {
195       Node JavaDoc child = children.item(i);
196       String JavaDoc nodeName = child.getNodeName();
197       if (child.getNodeType() == Node.CDATA_SECTION_NODE
198           || child.getNodeType() == Node.TEXT_NODE) {
199
200         String JavaDoc data = ((CharacterData JavaDoc) child).getData();
201         data = NodeletUtils.parsePropertyTokens(data, vars.properties);
202
203         SqlText sqlText;
204
205         if (postParseRequired) {
206           sqlText = new SqlText();
207           sqlText.setPostParseRequired(postParseRequired);
208           sqlText.setText(data.toString());
209         } else {
210           sqlText = PARAM_PARSER.parseInlineParameterMap(vars.client.getDelegate().getTypeHandlerFactory(), data.toString(), null);
211           sqlText.setPostParseRequired(postParseRequired);
212         }
213
214         dynamic.addChild(sqlText);
215
216         sqlBuffer.append(data);
217       } else if ("include".equals(nodeName)) {
218         Properties JavaDoc attributes = NodeletUtils.parseAttributes(child, vars.properties);
219         String JavaDoc refid = (String JavaDoc) attributes.get("refid");
220         Node JavaDoc includeNode = (Node JavaDoc) vars.sqlIncludes.get(refid);
221         if (includeNode == null) {
222           String JavaDoc nsrefid = applyNamespace(refid);
223           includeNode = (Node JavaDoc) vars.sqlIncludes.get(nsrefid);
224           if (includeNode == null) {
225             throw new NestedRuntimeException("Could not find SQL statement to include with refid '" + refid + "'");
226           }
227         }
228         isDynamic = parseDynamicTags(includeNode, dynamic, sqlBuffer, isDynamic, false);
229       } else {
230         vars.errorCtx.setMoreInfo("Check the dynamic tags.");
231
232         SqlTagHandler handler = SqlTagHandlerFactory.getSqlTagHandler(nodeName);
233         if (handler != null) {
234           isDynamic = true;
235
236           SqlTag tag = new SqlTag();
237           tag.setName(nodeName);
238           tag.setHandler(handler);
239
240           Properties JavaDoc attributes = NodeletUtils.parseAttributes(child, vars.properties);
241
242           tag.setPrependAttr(attributes.getProperty("prepend"));
243           tag.setPropertyAttr(attributes.getProperty("property"));
244           tag.setRemoveFirstPrepend(attributes.getProperty("removeFirstPrepend"));
245           
246           tag.setOpenAttr(attributes.getProperty("open"));
247           tag.setCloseAttr(attributes.getProperty("close"));
248
249           tag.setComparePropertyAttr(attributes.getProperty("compareProperty"));
250           tag.setCompareValueAttr(attributes.getProperty("compareValue"));
251           tag.setConjunctionAttr(attributes.getProperty("conjunction"));
252           
253           // an iterate ancestor requires a post parse
254

255           if(dynamic instanceof SqlTag) {
256             SqlTag parentSqlTag = (SqlTag)dynamic;
257             if(parentSqlTag.isPostParseRequired() ||
258                tag.getHandler() instanceof IterateTagHandler) {
259               tag.setPostParseRequired(true);
260             }
261           } else if (dynamic instanceof DynamicSql) {
262               if(tag.getHandler() instanceof IterateTagHandler) {
263                 tag.setPostParseRequired(true);
264               }
265           }
266
267           dynamic.addChild(tag);
268           
269           if (child.hasChildNodes()) {
270             isDynamic = parseDynamicTags(child, tag, sqlBuffer, isDynamic, tag.isPostParseRequired());
271           }
272         }
273       }
274     }
275     vars.errorCtx.setMoreInfo(null);
276     return isDynamic;
277   }
278
279   private SelectKeyStatement findAndParseSelectKeyStatement(Node JavaDoc n, GeneralStatement insertStatement) {
280     vars.errorCtx.setActivity("parsing select key tags");
281
282     SelectKeyStatement selectKeyStatement = null;
283
284     boolean foundTextFirst = false;
285
286     NodeList JavaDoc children = n.getChildNodes();
287     for (int i = 0; i < children.getLength(); i++) {
288       Node JavaDoc child = children.item(i);
289       if (child.getNodeType() == Node.CDATA_SECTION_NODE
290           || child.getNodeType() == Node.TEXT_NODE) {
291         String JavaDoc data = ((CharacterData JavaDoc) child).getData();
292         if (data.trim().length() > 0) {
293           foundTextFirst = true;
294         }
295       } else if (child.getNodeType() == Node.ELEMENT_NODE
296           && "selectKey".equals(child.getNodeName())) {
297         selectKeyStatement = parseSelectKey(child, insertStatement);
298         break;
299       }
300     }
301     if (selectKeyStatement != null) {
302       selectKeyStatement.setAfter(foundTextFirst);
303     }
304     vars.errorCtx.setMoreInfo(null);
305     return selectKeyStatement;
306   }
307
308   private SelectKeyStatement parseSelectKey(Node JavaDoc node, GeneralStatement insertStatement) {
309     vars.errorCtx.setActivity("parsing a select key");
310
311     // get attributes
312
Properties JavaDoc attributes = NodeletUtils.parseAttributes(node, vars.properties);
313     String JavaDoc keyPropName = attributes.getProperty("keyProperty");
314     String JavaDoc resultClassName = attributes.getProperty("resultClass");
315     resultClassName = vars.typeHandlerFactory.resolveAlias(resultClassName);
316     Class JavaDoc resultClass = null;
317
318     // get parameter and result maps
319
SelectKeyStatement selectKeyStatement = new SelectKeyStatement();
320     selectKeyStatement.setSqlMapClient(vars.client);
321
322     selectKeyStatement.setId(insertStatement.getId() + "-SelectKey");
323     selectKeyStatement.setResource(vars.errorCtx.getResource());
324     selectKeyStatement.setKeyProperty(keyPropName);
325
326     try {
327       if (resultClassName != null) {
328         vars.errorCtx.setMoreInfo("Check the select key result class.");
329         resultClass = Resources.classForName(resultClassName);
330       } else {
331         Class JavaDoc parameterClass = insertStatement.getParameterClass();
332         if (keyPropName != null && parameterClass != null) {
333           resultClass = PROBE.getPropertyTypeForSetter(parameterClass, selectKeyStatement.getKeyProperty());
334         }
335       }
336     } catch (ClassNotFoundException JavaDoc e) {
337       throw new SqlMapException("Error. Could not set result class. Cause: " + e, e);
338     }
339
340     if (resultClass == null) {
341       resultClass = Object JavaDoc.class;
342     }
343
344     // process SQL statement, including inline parameter maps
345
vars.errorCtx.setMoreInfo("Check the select key SQL statement.");
346     processSqlStatement(node, selectKeyStatement);
347
348     BasicResultMap resultMap;
349     resultMap = new AutoResultMap(vars.client.getDelegate(), false);
350     resultMap.setId(selectKeyStatement.getId() + "-AutoResultMap");
351     resultMap.setResultClass(resultClass);
352     resultMap.setResource(selectKeyStatement.getResource());
353     selectKeyStatement.setResultMap(resultMap);
354
355     vars.errorCtx.setMoreInfo(null);
356     return selectKeyStatement;
357   }
358
359   private void applyInlineParameterMap(GeneralStatement statement, String JavaDoc sqlStatement) {
360     String JavaDoc newSql = sqlStatement;
361
362     vars.errorCtx.setActivity("building an inline parameter map");
363
364     ParameterMap parameterMap = statement.getParameterMap();
365
366     vars.errorCtx.setMoreInfo("Check the inline parameters.");
367     if (parameterMap == null) {
368
369       BasicParameterMap map;
370       map = new BasicParameterMap(vars.client.getDelegate());
371
372       map.setId(statement.getId() + "-InlineParameterMap");
373       map.setParameterClass(statement.getParameterClass());
374       map.setResource(statement.getResource());
375       statement.setParameterMap(map);
376
377       SqlText sqlText = PARAM_PARSER.parseInlineParameterMap(vars.client.getDelegate().getTypeHandlerFactory(), newSql, statement.getParameterClass());
378       newSql = sqlText.getText();
379       List JavaDoc mappingList = Arrays.asList(sqlText.getParameterMappings());
380
381       map.setParameterMappingList(mappingList);
382
383     }
384
385     Sql sql = null;
386     if (SimpleDynamicSql.isSimpleDynamicSql(newSql)) {
387       sql = new SimpleDynamicSql(vars.client.getDelegate(), newSql);
388     } else {
389       sql = new StaticSql(newSql);
390     }
391     statement.setSql(sql);
392
393   }
394
395 }
396
Popular Tags