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