1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.sqlmap.engine.builder.xml;
17
18 import com.ibatis.common.xml.NodeletUtils;
19 import com.ibatis.sqlmap.engine.config.SqlSource;
20 import com.ibatis.sqlmap.engine.mapping.parameter.InlineParameterMapParser;
21 import com.ibatis.sqlmap.engine.mapping.sql.Sql;
22 import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
23 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSql;
24 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.*;
25 import com.ibatis.sqlmap.engine.mapping.sql.raw.RawSql;
26
27 import java.util.Properties;
28
29 import org.w3c.dom.CharacterData;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32
33
34
35
36 public class XMLSqlSource implements SqlSource {
37
38
39 private static final InlineParameterMapParser PARAM_PARSER = new InlineParameterMapParser();
40
41
42 private XmlParserState state;
43
44
45 private Node parentNode;
46
47
48
49
50
51
52
53
54
55 public XMLSqlSource(XmlParserState config, Node parentNode) {
56 this.state = config;
57 this.parentNode = parentNode;
58 }
59
60 public Sql getSql() {
61 state.getConfig().getErrorContext().setActivity("processing an SQL statement");
62
63 boolean isDynamic = false;
64 StringBuilder sqlBuffer = new StringBuilder();
65 DynamicSql dynamic = new DynamicSql(state.getConfig().getClient().getDelegate());
66 isDynamic = parseDynamicTags(parentNode, dynamic, sqlBuffer, isDynamic, false);
67 String sqlStatement = sqlBuffer.toString();
68 if (isDynamic) {
69 return dynamic;
70 } else {
71 return new RawSql(sqlStatement);
72 }
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 private boolean parseDynamicTags(Node node, DynamicParent dynamic, StringBuilder sqlBuffer, boolean isDynamic,
92 boolean postParseRequired) {
93 state.getConfig().getErrorContext().setActivity("parsing dynamic SQL tags");
94
95 NodeList children = node.getChildNodes();
96 for (int i = 0; i < children.getLength(); i++) {
97 Node child = children.item(i);
98 String nodeName = child.getNodeName();
99 if (child.getNodeType() == Node.CDATA_SECTION_NODE || child.getNodeType() == Node.TEXT_NODE) {
100
101 String data = ((CharacterData) child).getData();
102 data = NodeletUtils.parsePropertyTokens(data, state.getGlobalProps());
103
104 SqlText sqlText;
105
106 if (postParseRequired) {
107 sqlText = new SqlText();
108 sqlText.setPostParseRequired(postParseRequired);
109 sqlText.setText(data);
110 } else {
111 sqlText = PARAM_PARSER
112 .parseInlineParameterMap(state.getConfig().getClient().getDelegate().getTypeHandlerFactory(), data, null);
113 sqlText.setPostParseRequired(postParseRequired);
114 }
115
116 dynamic.addChild(sqlText);
117
118 sqlBuffer.append(data);
119 } else if ("include".equals(nodeName)) {
120 Properties attributes = NodeletUtils.parseAttributes(child, state.getGlobalProps());
121 String refid = (String) attributes.get("refid");
122 Node includeNode = (Node) state.getSqlIncludes().get(refid);
123 if (includeNode == null) {
124 String nsrefid = state.applyNamespace(refid);
125 includeNode = (Node) state.getSqlIncludes().get(nsrefid);
126 if (includeNode == null) {
127 throw new RuntimeException("Could not find SQL statement to include with refid '" + refid + "'");
128 }
129 }
130 isDynamic = parseDynamicTags(includeNode, dynamic, sqlBuffer, isDynamic, false);
131 } else {
132 state.getConfig().getErrorContext().setMoreInfo("Check the dynamic tags.");
133
134 SqlTagHandler handler = SqlTagHandlerFactory.getSqlTagHandler(nodeName);
135 if (handler != null) {
136 isDynamic = true;
137
138 SqlTag tag = new SqlTag();
139 tag.setName(nodeName);
140 tag.setHandler(handler);
141
142 Properties attributes = NodeletUtils.parseAttributes(child, state.getGlobalProps());
143
144 tag.setPrependAttr(attributes.getProperty("prepend"));
145 tag.setPropertyAttr(attributes.getProperty("property"));
146 tag.setRemoveFirstPrepend(attributes.getProperty("removeFirstPrepend"));
147
148 tag.setOpenAttr(attributes.getProperty("open"));
149 tag.setCloseAttr(attributes.getProperty("close"));
150
151 tag.setComparePropertyAttr(attributes.getProperty("compareProperty"));
152 tag.setCompareValueAttr(attributes.getProperty("compareValue"));
153 tag.setConjunctionAttr(attributes.getProperty("conjunction"));
154
155
156
157 if (dynamic instanceof SqlTag) {
158 SqlTag parentSqlTag = (SqlTag) dynamic;
159 if (parentSqlTag.isPostParseRequired() || tag.getHandler() instanceof IterateTagHandler) {
160 tag.setPostParseRequired(true);
161 }
162 } else if (dynamic instanceof DynamicSql) {
163 if (tag.getHandler() instanceof IterateTagHandler) {
164 tag.setPostParseRequired(true);
165 }
166 }
167
168 dynamic.addChild(tag);
169
170 if (child.hasChildNodes()) {
171 isDynamic = parseDynamicTags(child, tag, sqlBuffer, isDynamic, tag.isPostParseRequired());
172 }
173 }
174 }
175 }
176 state.getConfig().getErrorContext().setMoreInfo(null);
177 return isDynamic;
178 }
179
180 }