001: /*
002: * XMLConfiguration.java
003: *
004: * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.xml;
010:
011: import pnuts.lang.Context;
012: import pnuts.lang.Configuration;
013: import org.w3c.dom.NodeList;
014: import org.w3c.dom.Node;
015: import org.w3c.dom.NamedNodeMap;
016: import org.w3c.dom.Element;
017: import java.util.Enumeration;
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022: import org.pnuts.lib.AggregateConfiguration;
023: import org.w3c.dom.Attr;
024: import org.w3c.dom.Text;
025:
026: /**
027: * This class provides an easier way to access NodeList.
028: *
029: * (1) Index access to NodeList.
030: * e.g. nodeList[i]
031: *
032: * (2) Iterate NodeList with for/foreach statement
033: * e.g. for (i : nodeList) ...
034: *
035: * (3) Attributes
036: * e.g. node["attributeName"]
037: *
038: * (4) Navigation
039: * e.g. document.project.target.name
040: */
041: public class XMLConfiguration extends AggregateConfiguration {
042:
043: private final static String TEXT = "text".intern();
044: private final static String TEXT_TRIM = "textTrim".intern();
045: private final static String GET_CHILDREN = "getChildren".intern();
046: private final static String GET_CHILD = "getChild".intern();
047: private final static String ATTRIBUTES = "attributes".intern();
048:
049: public XMLConfiguration() {
050: }
051:
052: public XMLConfiguration(Configuration base) {
053: super (base);
054: }
055:
056: static class NodeListEnum implements Enumeration {
057: NodeList nodeList;
058: int idx;
059: int len;
060:
061: NodeListEnum(NodeList nodeList) {
062: this .nodeList = nodeList;
063: this .idx = 0;
064: this .len = nodeList.getLength();
065: }
066:
067: public boolean hasMoreElements() {
068: return idx < len;
069: }
070:
071: public Object nextElement() {
072: return nodeList.item(idx++);
073: }
074: }
075:
076: static List findNodes(Node node, String name) {
077: NodeList nodeList = node.getChildNodes();
078: ArrayList lst = new ArrayList();
079: for (int i = 0; i < nodeList.getLength(); i++) {
080: Node n = nodeList.item(i);
081: if (n.getNodeName().equals(name)) {
082: lst.add(n);
083: }
084: }
085: return lst;
086: }
087:
088: static String getText(Node node) {
089: NodeList nodeList = node.getChildNodes();
090: int len = nodeList.getLength();
091: for (int i = 0; i < len; i++) {
092: Node n = nodeList.item(i);
093: if (n instanceof Text) {
094: return n.getNodeValue();
095: }
096: }
097: return "";
098: }
099:
100: static Element getElement(NodeList nodeList, String skey) {
101: int len = nodeList.getLength();
102: for (int i = 0; i < len; i++) {
103: Node n = nodeList.item(i);
104: if (n instanceof Element) {
105: Element e = (Element) n;
106: if (e.getTagName().equals(skey)) {
107: return e;
108: }
109: }
110: }
111: return null;
112: }
113:
114: static Element getElement(NodeList nodeList, int idx) {
115: int len = nodeList.getLength();
116: int count = 0;
117: for (int i = 0; i < len; i++) {
118: Node n = nodeList.item(i);
119: if (n instanceof Element) {
120: if (idx == count) {
121: return (Element) n;
122: }
123: count++;
124: }
125: }
126: return null;
127: }
128:
129: public Object getElement(Context context, Object target, Object key) {
130: String skey = null;
131: int idx = 0;
132:
133: if (key instanceof Number) {
134: idx = ((Number) key).intValue();
135: } else if (key instanceof String) {
136: skey = (String) key;
137: } else {
138: return super .getElement(context, target, key);
139: }
140: if ((target instanceof Element) && skey != null) {
141: if (skey.charAt(0) == '@') {
142: return ((Element) target).getAttribute(skey
143: .substring(1));
144: } else {
145: return getElement(((Element) target).getChildNodes(),
146: skey);
147: }
148: } else if (target instanceof NodeList) {
149: NodeList nodeList = (NodeList) target;
150: if (skey == null) {
151: return getElement(nodeList, idx);
152: } else {
153: return getElement(nodeList, skey);
154: }
155: } else if (target instanceof NamedNodeMap) {
156: NamedNodeMap nodeMap = (NamedNodeMap) target;
157: if (skey != null) {
158: return nodeMap.getNamedItem(skey);
159: } else {
160: return nodeMap.item(idx);
161: }
162: }
163: return super .getElement(context, target, key);
164: }
165:
166: public void setElement(Context context, Object target, Object key,
167: Object value) {
168: String skey = null;
169: if (key instanceof String) {
170: skey = (String) key;
171: if (target instanceof Element) {
172: if (skey.charAt(0) == '@')
173: skey = skey.substring(1);
174: ((Element) target).setAttribute(skey, (String) value);
175: return;
176: }
177: }
178: super .setElement(context, target, key, value);
179: }
180:
181: public Object getField(Context context, Object target, String name) {
182: if (target instanceof Node) {
183: if (name == TEXT) {
184: return getText((Node) target);
185: } else if (name == TEXT_TRIM) {
186: return getText((Node) target).trim();
187: } else if (name == ATTRIBUTES) {
188: NamedNodeMap nodeMap = ((Node) target).getAttributes();
189: Element element = null;
190: if (target instanceof Element) {
191: element = (Element) target;
192: }
193: return new DOMAttributeMap(element, nodeMap);
194: }
195: List lst = findNodes((Node) target, name);
196: int size = lst.size();
197: if (size == 0) {
198: if (name.charAt(0) == '@' && target instanceof Element) {
199: return ((Element) target).getAttribute(name
200: .substring(1));
201: }
202: return null;
203: } else {
204: return lst;
205: }
206: } else if (target instanceof NamedNodeMap) {
207: NamedNodeMap m = (NamedNodeMap) target;
208: return m.getNamedItem(name);
209: } else {
210: return super .getField(context, target, name);
211: }
212: }
213:
214: public void putField(Context context, Object target, String name,
215: Object value) {
216: if (target instanceof Element) {
217: if (name == TEXT) {
218: if (value instanceof String) {
219: ((Element) target).setTextContent((String) value);
220: }
221: } else if (name == ATTRIBUTES) {
222: if (value instanceof Map) {
223: Element element = (Element) target;
224: NamedNodeMap m = element.getAttributes();
225: int len = m.getLength();
226: for (int i = 0; i < len; i++) {
227: Attr attr = (Attr) m.item(i);
228: element.removeAttributeNode(attr);
229: }
230: for (Iterator it = ((Map) value).entrySet()
231: .iterator(); it.hasNext();) {
232: Map.Entry entry = (Map.Entry) it.next();
233: element.setAttribute((String) entry.getKey(),
234: (String) entry.getValue());
235: }
236: }
237: } else if (name.charAt(0) == '@' && value instanceof String) {
238: ((Element) target).setAttribute(name.substring(1),
239: (String) value);
240: } else {
241: super .putField(context, target, name, value);
242: }
243: } else {
244: super .putField(context, target, name, value);
245: }
246: }
247:
248: public Object callMethod(Context context, Class c, String name,
249: Object args[], Class types[], Object target) {
250: if (target instanceof Node) {
251: Node node = (Node) target;
252: if (name == GET_CHILD && args.length == 1) {
253: String tag = (String) args[0];
254: NodeList nodeList = node.getChildNodes();
255: int len = nodeList.getLength();
256: for (int i = 0; i < len; i++) {
257: Node n = nodeList.item(i);
258: if (n instanceof Element) {
259: if (((Element) n).getTagName().equals(tag)) {
260: return n;
261: }
262: }
263: }
264: return null;
265: } else if (name == GET_CHILDREN) {
266: List list = new ArrayList();
267: NodeList nodeList = node.getChildNodes();
268: if (args.length == 1) {
269: String tag = (String) args[0];
270: for (int i = 0; i < nodeList.getLength(); i++) {
271: Node n = nodeList.item(i);
272: if (n instanceof Element) {
273: if (((Element) n).getTagName().equals(tag)) {
274: list.add(n);
275: }
276: }
277: }
278: } else if (args.length == 0) {
279: for (int i = 0; i < nodeList.getLength(); i++) {
280: Node n = nodeList.item(i);
281: if (n instanceof Element) {
282: list.add(n);
283: }
284: }
285: }
286: return list;
287: }
288: }
289: return super .callMethod(context, c, name, args, types, target);
290: }
291:
292: public Enumeration toEnumeration(Object object) {
293: if (object instanceof NodeList) {
294: return new NodeListEnum((NodeList) object);
295: } else {
296: return super.toEnumeration(object);
297: }
298: }
299: }
|