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