1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.common.beans;
17
18 import com.ibatis.common.resources.Resources;
19
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.StringTokenizer;
27
28 import org.w3c.dom.CharacterData;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34 import org.w3c.dom.Text;
35
36
37
38
39 public class DomProbe extends BaseProbe {
40
41 @Override
42 public String[] getReadablePropertyNames(Object object) {
43 List props = new ArrayList<>();
44 Element e = resolveElement(object);
45 NodeList nodes = e.getChildNodes();
46 for (int i = 0; i < nodes.getLength(); i++) {
47 props.add(nodes.item(i).getNodeName());
48 }
49 return (String[]) props.toArray(new String[props.size()]);
50 }
51
52 @Override
53 public String[] getWriteablePropertyNames(Object object) {
54 List props = new ArrayList<>();
55 Element e = resolveElement(object);
56 NodeList nodes = e.getChildNodes();
57 for (int i = 0; i < nodes.getLength(); i++) {
58 props.add(nodes.item(i).getNodeName());
59 }
60 return (String[]) props.toArray(new String[props.size()]);
61 }
62
63 @Override
64 public Class getPropertyTypeForSetter(Object object, String name) {
65 Element e = findNestedNodeByName(resolveElement(object), name, false);
66
67 try {
68 return Resources.classForName(e.getAttribute("type"));
69 } catch (ClassNotFoundException e1) {
70 return Object.class;
71 }
72 }
73
74 @Override
75 public Class getPropertyTypeForGetter(Object object, String name) {
76 Element e = findNestedNodeByName(resolveElement(object), name, false);
77
78 try {
79 return Resources.classForName(e.getAttribute("type"));
80 } catch (ClassNotFoundException e1) {
81 return Object.class;
82 }
83 }
84
85 @Override
86 public boolean hasWritableProperty(Object object, String propertyName) {
87 return findNestedNodeByName(resolveElement(object), propertyName, false) != null;
88 }
89
90 @Override
91 public boolean hasReadableProperty(Object object, String propertyName) {
92 return findNestedNodeByName(resolveElement(object), propertyName, false) != null;
93 }
94
95 @Override
96 public Object getObject(Object object, String name) {
97 Object value = null;
98 Element element = findNestedNodeByName(resolveElement(object), name, false);
99 if (element != null) {
100 value = getElementValue(element);
101 }
102 return value;
103 }
104
105 @Override
106 public void setObject(Object object, String name, Object value) {
107 Element element = findNestedNodeByName(resolveElement(object), name, true);
108 if (element != null) {
109 setElementValue(element, value);
110 }
111 }
112
113 @Override
114 protected void setProperty(Object object, String property, Object value) {
115 Element element = findNodeByName(resolveElement(object), property, 0, true);
116 if (element != null) {
117 setElementValue(element, value);
118 }
119 }
120
121 @Override
122 protected Object getProperty(Object object, String property) {
123 Object value = null;
124 Element element = findNodeByName(resolveElement(object), property, 0, false);
125 if (element != null) {
126 value = getElementValue(element);
127 }
128 return value;
129 }
130
131
132
133
134
135
136
137
138
139 private Element resolveElement(Object object) {
140 Element element = null;
141 if (object instanceof Document) {
142 element = (Element) ((Document) object).getLastChild();
143 } else if (object instanceof Element) {
144 element = (Element) object;
145 } else {
146 throw new ProbeException("An unknown object type was passed to DomProbe. Must be a Document.");
147 }
148 return element;
149 }
150
151
152
153
154
155
156
157
158
159 private void setElementValue(Element element, Object value) {
160 CharacterData data = null;
161
162 Element prop = element;
163
164 if (value instanceof Collection) {
165 Iterator items = ((Collection) value).iterator();
166 while (items.hasNext()) {
167 Document valdoc = (Document) items.next();
168 NodeList list = valdoc.getChildNodes();
169 for (int i = 0; i < list.getLength(); i++) {
170 Node newNode = element.getOwnerDocument().importNode(list.item(i), true);
171 element.appendChild(newNode);
172 }
173 }
174 } else if (value instanceof Document) {
175 Document valdoc = (Document) value;
176 Node lastChild = valdoc.getLastChild();
177 NodeList list = lastChild.getChildNodes();
178 for (int i = 0; i < list.getLength(); i++) {
179 Node newNode = element.getOwnerDocument().importNode(list.item(i), true);
180 element.appendChild(newNode);
181 }
182 } else if (value instanceof Element) {
183 Node newNode = element.getOwnerDocument().importNode((Element) value, true);
184 element.appendChild(newNode);
185 } else {
186
187 NodeList texts = prop.getChildNodes();
188 if (texts.getLength() == 1) {
189 Node child = texts.item(0);
190 if (child instanceof CharacterData) {
191
192 data = (CharacterData) child;
193 } else {
194
195 prop.removeChild(child);
196 Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
197 prop.appendChild(text);
198 data = text;
199 }
200 } else if (texts.getLength() > 1) {
201
202 for (int i = texts.getLength() - 1; i >= 0; i--) {
203 prop.removeChild(texts.item(i));
204 }
205 Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
206 prop.appendChild(text);
207 data = text;
208 } else {
209
210 Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
211 prop.appendChild(text);
212 data = text;
213 }
214 data.setData(String.valueOf(value));
215 }
216
217
218
219
220 }
221
222
223
224
225
226
227
228
229
230 private Object getElementValue(Element element) {
231 StringBuilder value = null;
232
233 Element prop = element;
234
235 if (prop != null) {
236
237 NodeList texts = prop.getChildNodes();
238 if (texts.getLength() > 0) {
239 value = new StringBuilder();
240 for (int i = 0; i < texts.getLength(); i++) {
241 Node text = texts.item(i);
242 if (text instanceof CharacterData) {
243 value.append(((CharacterData) text).getData());
244 }
245 }
246 }
247 }
248
249
250
251
252 if (value == null) {
253 return null;
254 }
255 return value.toString();
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270 private Element findNestedNodeByName(Element element, String name, boolean create) {
271 Element child = element;
272
273 StringTokenizer parser = new StringTokenizer(name, ".", false);
274 while (parser.hasMoreTokens()) {
275 String childName = parser.nextToken();
276 if (childName.indexOf('[') > -1) {
277 String propName = childName.substring(0, childName.indexOf('['));
278 int i = Integer.parseInt(childName.substring(childName.indexOf('[') + 1, childName.indexOf(']')));
279 child = findNodeByName(child, propName, i, create);
280 } else {
281 child = findNodeByName(child, childName, 0, create);
282 }
283 if (child == null) {
284 break;
285 }
286 }
287
288 return child;
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 private Element findNodeByName(Element element, String name, int index, boolean create) {
306 Element prop = null;
307
308
309 NodeList propNodes = element.getElementsByTagName(name);
310 if (propNodes.getLength() > index) {
311 prop = (Element) propNodes.item(index);
312 } else if (create) {
313 for (int i = 0; i < index + 1; i++) {
314 prop = element.getOwnerDocument().createElement(name);
315 element.appendChild(prop);
316 }
317 }
318 return prop;
319 }
320
321
322
323
324
325
326
327
328
329
330
331 public static String nodeToString(Node node, String indent) {
332 StringWriter stringWriter = new StringWriter();
333 PrintWriter printWriter = new PrintWriter(stringWriter);
334
335 switch (node.getNodeType()) {
336
337 case Node.DOCUMENT_NODE:
338 printWriter.println("<xml version=\"1.0\">\n");
339
340 NodeList nodes = node.getChildNodes();
341 if (nodes != null) {
342 for (int i = 0; i < nodes.getLength(); i++) {
343 printWriter.print(nodeToString(nodes.item(i), ""));
344 }
345 }
346 break;
347
348 case Node.ELEMENT_NODE:
349 String name = node.getNodeName();
350 printWriter.print(indent + "<" + name);
351 NamedNodeMap attributes = node.getAttributes();
352 for (int i = 0; i < attributes.getLength(); i++) {
353 Node current = attributes.item(i);
354 printWriter.print(" " + current.getNodeName() + "=\"" + current.getNodeValue() + "\"");
355 }
356 printWriter.print(">");
357
358
359 NodeList children = node.getChildNodes();
360 if (children != null) {
361 for (int i = 0; i < children.getLength(); i++) {
362 printWriter.print(nodeToString(children.item(i), indent + indent));
363 }
364 }
365
366 printWriter.print("</" + name + ">");
367 break;
368
369 case Node.TEXT_NODE:
370 printWriter.print(node.getNodeValue());
371 break;
372 }
373
374 printWriter.flush();
375 String result = stringWriter.getBuffer().toString();
376 printWriter.close();
377
378 return result;
379 }
380
381 }