View Javadoc
1   /**
2    *    Copyright 2009-2015 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.parsing;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Properties;
22  
23  import org.w3c.dom.CharacterData;
24  import org.w3c.dom.Element;
25  import org.w3c.dom.NamedNodeMap;
26  import org.w3c.dom.Node;
27  import org.w3c.dom.NodeList;
28  
29  /**
30   * @author Clinton Begin
31   */
32  public class XNode {
33  
34    private Node node;
35    private String name;
36    private String body;
37    private Properties attributes;
38    private Properties variables;
39    private XPathParser xpathParser;
40  
41    public XNode(XPathParser xpathParser, Node node, Properties variables) {
42      this.xpathParser = xpathParser;
43      this.node = node;
44      this.name = node.getNodeName();
45      this.variables = variables;
46      this.attributes = parseAttributes(node);
47      this.body = parseBody(node);
48    }
49  
50    public XNode newXNode(Node node) {
51      return new XNode(xpathParser, node, variables);
52    }
53  
54    public XNode getParent() {
55      Node parent = node.getParentNode();
56      if (parent == null || !(parent instanceof Element)) {
57        return null;
58      } else {
59        return new XNode(xpathParser, parent, variables);
60      }
61    }
62  
63    public String getPath() {
64      StringBuilder builder = new StringBuilder();
65      Node current = node;
66      while (current != null && current instanceof Element) {
67        if (current != node) {
68          builder.insert(0, "/");
69        }
70        builder.insert(0, current.getNodeName());
71        current = current.getParentNode();
72      }
73      return builder.toString();
74    }
75  
76    public String getValueBasedIdentifier() {
77      StringBuilder builder = new StringBuilder();
78      XNode current = this;
79      while (current != null) {
80        if (current != this) {
81          builder.insert(0, "_");
82        }
83        String value = current.getStringAttribute("id",
84            current.getStringAttribute("value",
85                current.getStringAttribute("property", null)));
86        if (value != null) {
87          value = value.replace('.', '_');
88          builder.insert(0, "]");
89          builder.insert(0,
90              value);
91          builder.insert(0, "[");
92        }
93        builder.insert(0, current.getName());
94        current = current.getParent();
95      }
96      return builder.toString();
97    }
98  
99    public String evalString(String expression) {
100     return xpathParser.evalString(node, expression);
101   }
102 
103   public Boolean evalBoolean(String expression) {
104     return xpathParser.evalBoolean(node, expression);
105   }
106 
107   public Double evalDouble(String expression) {
108     return xpathParser.evalDouble(node, expression);
109   }
110 
111   public List<XNode> evalNodes(String expression) {
112     return xpathParser.evalNodes(node, expression);
113   }
114 
115   public XNode evalNode(String expression) {
116     return xpathParser.evalNode(node, expression);
117   }
118 
119   public Node getNode() {
120     return node;
121   }
122 
123   public String getName() {
124     return name;
125   }
126 
127   public String getStringBody() {
128     return getStringBody(null);
129   }
130 
131   public String getStringBody(String def) {
132     if (body == null) {
133       return def;
134     } else {
135       return body;
136     }
137   }
138 
139   public Boolean getBooleanBody() {
140     return getBooleanBody(null);
141   }
142 
143   public Boolean getBooleanBody(Boolean def) {
144     if (body == null) {
145       return def;
146     } else {
147       return Boolean.valueOf(body);
148     }
149   }
150 
151   public Integer getIntBody() {
152     return getIntBody(null);
153   }
154 
155   public Integer getIntBody(Integer def) {
156     if (body == null) {
157       return def;
158     } else {
159       return Integer.parseInt(body);
160     }
161   }
162 
163   public Long getLongBody() {
164     return getLongBody(null);
165   }
166 
167   public Long getLongBody(Long def) {
168     if (body == null) {
169       return def;
170     } else {
171       return Long.parseLong(body);
172     }
173   }
174 
175   public Double getDoubleBody() {
176     return getDoubleBody(null);
177   }
178 
179   public Double getDoubleBody(Double def) {
180     if (body == null) {
181       return def;
182     } else {
183       return Double.parseDouble(body);
184     }
185   }
186 
187   public Float getFloatBody() {
188     return getFloatBody(null);
189   }
190 
191   public Float getFloatBody(Float def) {
192     if (body == null) {
193       return def;
194     } else {
195       return Float.parseFloat(body);
196     }
197   }
198 
199   public <T extends Enum<T>> T getEnumAttribute(Class<T> enumType, String name) {
200     return getEnumAttribute(enumType, name, null);
201   }
202 
203   public <T extends Enum<T>> T getEnumAttribute(Class<T> enumType, String name, T def) {
204     String value = getStringAttribute(name);
205     if (value == null) {
206       return def;
207     } else {
208       return Enum.valueOf(enumType, value);
209     }
210   }
211 
212   public String getStringAttribute(String name) {
213     return getStringAttribute(name, null);
214   }
215 
216   public String getStringAttribute(String name, String def) {
217     String value = attributes.getProperty(name);
218     if (value == null) {
219       return def;
220     } else {
221       return value;
222     }
223   }
224 
225   public Boolean getBooleanAttribute(String name) {
226     return getBooleanAttribute(name, null);
227   }
228 
229   public Boolean getBooleanAttribute(String name, Boolean def) {
230     String value = attributes.getProperty(name);
231     if (value == null) {
232       return def;
233     } else {
234       return Boolean.valueOf(value);
235     }
236   }
237 
238   public Integer getIntAttribute(String name) {
239     return getIntAttribute(name, null);
240   }
241 
242   public Integer getIntAttribute(String name, Integer def) {
243     String value = attributes.getProperty(name);
244     if (value == null) {
245       return def;
246     } else {
247       return Integer.parseInt(value);
248     }
249   }
250 
251   public Long getLongAttribute(String name) {
252     return getLongAttribute(name, null);
253   }
254 
255   public Long getLongAttribute(String name, Long def) {
256     String value = attributes.getProperty(name);
257     if (value == null) {
258       return def;
259     } else {
260       return Long.parseLong(value);
261     }
262   }
263 
264   public Double getDoubleAttribute(String name) {
265     return getDoubleAttribute(name, null);
266   }
267 
268   public Double getDoubleAttribute(String name, Double def) {
269     String value = attributes.getProperty(name);
270     if (value == null) {
271       return def;
272     } else {
273       return Double.parseDouble(value);
274     }
275   }
276 
277   public Float getFloatAttribute(String name) {
278     return getFloatAttribute(name, null);
279   }
280 
281   public Float getFloatAttribute(String name, Float def) {
282     String value = attributes.getProperty(name);
283     if (value == null) {
284       return def;
285     } else {
286       return Float.parseFloat(value);
287     }
288   }
289 
290   public List<XNode> getChildren() {
291     List<XNode> children = new ArrayList<XNode>();
292     NodeList nodeList = node.getChildNodes();
293     if (nodeList != null) {
294       for (int i = 0, n = nodeList.getLength(); i < n; i++) {
295         Node node = nodeList.item(i);
296         if (node.getNodeType() == Node.ELEMENT_NODE) {
297           children.add(new XNode(xpathParser, node, variables));
298         }
299       }
300     }
301     return children;
302   }
303 
304   public Properties getChildrenAsProperties() {
305     Properties properties = new Properties();
306     for (XNode child : getChildren()) {
307       String name = child.getStringAttribute("name");
308       String value = child.getStringAttribute("value");
309       if (name != null && value != null) {
310         properties.setProperty(name, value);
311       }
312     }
313     return properties;
314   }
315 
316   @Override
317   public String toString() {
318     StringBuilder builder = new StringBuilder();
319     builder.append("<");
320     builder.append(name);
321     for (Map.Entry<Object, Object> entry : attributes.entrySet()) {
322       builder.append(" ");
323       builder.append(entry.getKey());
324       builder.append("=\"");
325       builder.append(entry.getValue());
326       builder.append("\"");
327     }
328     List<XNode> children = getChildren();
329     if (!children.isEmpty()) {
330       builder.append(">\n");
331       for (XNode node : children) {
332         builder.append(node.toString());
333       }
334       builder.append("</");
335       builder.append(name);
336       builder.append(">");
337     } else if (body != null) {
338       builder.append(">");
339       builder.append(body);
340       builder.append("</");
341       builder.append(name);
342       builder.append(">");
343     } else {
344       builder.append("/>");
345     }
346     builder.append("\n");
347     return builder.toString();
348   }
349 
350   private Properties parseAttributes(Node n) {
351     Properties attributes = new Properties();
352     NamedNodeMap attributeNodes = n.getAttributes();
353     if (attributeNodes != null) {
354       for (int i = 0; i < attributeNodes.getLength(); i++) {
355         Node attribute = attributeNodes.item(i);
356         String value = PropertyParser.parse(attribute.getNodeValue(), variables);
357         attributes.put(attribute.getNodeName(), value);
358       }
359     }
360     return attributes;
361   }
362 
363   private String parseBody(Node node) {
364     String data = getBodyData(node);
365     if (data == null) {
366       NodeList children = node.getChildNodes();
367       for (int i = 0; i < children.getLength(); i++) {
368         Node child = children.item(i);
369         data = getBodyData(child);
370         if (data != null) {
371           break;
372         }
373       }
374     }
375     return data;
376   }
377 
378   private String getBodyData(Node child) {
379     if (child.getNodeType() == Node.CDATA_SECTION_NODE
380         || child.getNodeType() == Node.TEXT_NODE) {
381       String data = ((CharacterData) child).getData();
382       data = PropertyParser.parse(data, variables);
383       return data;
384     }
385     return null;
386   }
387 
388 }