001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.views.xslt;
006:
007: import org.apache.commons.logging.LogFactory;
008: import org.apache.commons.logging.Log;
009: import org.w3c.dom.*;
010: import java.util.List;
011: import java.util.ArrayList;
012: import java.util.LinkedList;
013: import java.util.Iterator;
014:
015: import com.opensymphony.webwork.WebWorkException;
016:
017: /**
018: * AbstractAdapterNode is the base for childAdapters that expose a read-only view
019: * of a Java object as a DOM Node. This class implements the core parent-child
020: * and sibling node traversal functionality shared by all adapter type nodes
021: * and used in proxy node support.
022: *
023: * @author <a href="mailto:meier@meisterbohne.de">Philipp Meier</a>
024: * @author Pat Niemeyer pat@pat.net
025: * @see AbstractAdapterElement
026: */
027: public abstract class AbstractAdapterNode implements AdapterNode {
028: //~ Static fields/initializers /////////////////////////////////////////////
029:
030: private static final NamedNodeMap EMPTY_NAMEDNODEMAP = new NamedNodeMap() {
031: public int getLength() {
032: return 0;
033: }
034:
035: public Node item(int index) {
036: return null;
037: }
038:
039: public Node getNamedItem(String name) {
040: return null;
041: }
042:
043: public Node removeNamedItem(String name) throws DOMException {
044: return null;
045: }
046:
047: public Node setNamedItem(Node arg) throws DOMException {
048: return null;
049: }
050:
051: public Node setNamedItemNS(Node arg) throws DOMException {
052: return null;
053: }
054:
055: public Node getNamedItemNS(String namespaceURI, String localName) {
056: return null;
057: }
058:
059: public Node removeNamedItemNS(String namespaceURI,
060: String localName) throws DOMException {
061: return null;
062: }
063: };
064:
065: //~ Instance fields ////////////////////////////////////////////////////////
066:
067: private List childAdapters;
068: private Log log = LogFactory.getLog(this .getClass());
069: // The domain object that we are adapting
070: private Object propertyValue;
071: private String propertyName;
072: private AdapterNode parent;
073: private AdapterFactory adapterFactory;
074:
075: //~ Constructors ///////////////////////////////////////////////////////////
076:
077: public AbstractAdapterNode() {
078: if (LogFactory.getLog(getClass()).isDebugEnabled()) {
079: LogFactory.getLog(getClass()).debug("Creating " + this );
080: }
081: }
082:
083: //~ Methods ////////////////////////////////////////////////////////////////
084:
085: protected void setContext(AdapterFactory adapterFactory,
086: AdapterNode parent, String propertyName, Object value) {
087: setAdapterFactory(adapterFactory);
088: setParent(parent);
089: setPropertyName(propertyName);
090: setPropertyValue(value);
091: }
092:
093: /**
094: * subclasses override to produce their children
095: * @return
096: */
097: protected List buildChildAdapters() {
098: return new ArrayList();
099: }
100:
101: /**
102: * Lazily initialize child childAdapters
103: */
104: protected List getChildAdapters() {
105: if (childAdapters == null)
106: childAdapters = buildChildAdapters();
107: return childAdapters;
108: }
109:
110: public Node getChildBeforeOrAfter(Node child, boolean before) {
111: log.debug("getChildBeforeOrAfter: ");
112: List adapters = getChildAdapters();
113: log.debug("childAdapters = " + adapters);
114: log.debug("child = " + child);
115: int index = adapters.indexOf(child);
116: if (index < 0)
117: throw new WebWorkException(child + " is no child of "
118: + this );
119: int siblingIndex = before ? index - 1 : index + 1;
120: return ((0 < siblingIndex) && (siblingIndex < adapters.size())) ? ((Node) adapters
121: .get(siblingIndex))
122: : null;
123: }
124:
125: public Node getChildAfter(Node child) {
126: log.trace("getChildafter");
127: return getChildBeforeOrAfter(child, false/*after*/);
128: }
129:
130: public Node getChildBefore(Node child) {
131: log.trace("getchildbefore");
132: return getChildBeforeOrAfter(child, true/*after*/);
133: }
134:
135: public NodeList getElementsByTagName(String tagName) {
136: if (tagName.equals("*")) {
137: return getChildNodes();
138: } else {
139: LinkedList filteredChildren = new LinkedList();
140:
141: for (Iterator i = getChildAdapters().iterator(); i
142: .hasNext();) {
143: Node adapterNode = (Node) i.next();
144:
145: if (adapterNode.getNodeName().equals(tagName)) {
146: filteredChildren.add(adapterNode);
147: }
148: }
149:
150: return new SimpleNodeList(filteredChildren);
151: }
152: }
153:
154: public NodeList getElementsByTagNameNS(String string, String string1) {
155: // TODO:
156: return null;
157: }
158:
159: // Begin Node methods
160:
161: public NamedNodeMap getAttributes() {
162: return EMPTY_NAMEDNODEMAP;
163: }
164:
165: public NodeList getChildNodes() {
166: NodeList nl = new SimpleNodeList(getChildAdapters());
167: if (log.isDebugEnabled())
168: log.debug("getChildNodes for tag: " + getNodeName()
169: + " num children: " + nl.getLength());
170: return nl;
171: }
172:
173: public Node getFirstChild() {
174: return (getChildNodes().getLength() > 0) ? getChildNodes()
175: .item(0) : null;
176: }
177:
178: public Node getLastChild() {
179: return (getChildNodes().getLength() > 0) ? getChildNodes()
180: .item(getChildNodes().getLength() - 1) : null;
181: }
182:
183: public String getLocalName() {
184: return null;
185: }
186:
187: public String getNamespaceURI() {
188: return null;
189: }
190:
191: public void setNodeValue(String string) throws DOMException {
192: throw operationNotSupported();
193: }
194:
195: public String getNodeValue() throws DOMException {
196: throw operationNotSupported();
197: }
198:
199: public Document getOwnerDocument() {
200: return null;
201: }
202:
203: public Node getParentNode() {
204: log.trace("getParentNode");
205: return getParent();
206: }
207:
208: public AdapterNode getParent() {
209: return parent;
210: }
211:
212: public void setParent(AdapterNode parent) {
213: this .parent = parent;
214: }
215:
216: public Object getPropertyValue() {
217: return propertyValue;
218: }
219:
220: public void setPropertyValue(Object prop) {
221: this .propertyValue = prop;
222: }
223:
224: public void setPrefix(String string) throws DOMException {
225: throw operationNotSupported();
226: }
227:
228: public String getPrefix() {
229: return null;
230: }
231:
232: public Node getNextSibling() {
233: Node next = getParent().getChildAfter(this );
234: if (log.isTraceEnabled()) {
235: log.trace("getNextSibling on " + getNodeName() + ": "
236: + ((next == null) ? "null" : next.getNodeName()));
237: }
238:
239: return getParent().getChildAfter(this );
240: }
241:
242: public Node getPreviousSibling() {
243: return getParent().getChildBefore(this );
244: }
245:
246: public String getPropertyName() {
247: return propertyName;
248: }
249:
250: public void setPropertyName(String name) {
251: this .propertyName = name;
252: }
253:
254: public AdapterFactory getAdapterFactory() {
255: return adapterFactory;
256: }
257:
258: public void setAdapterFactory(AdapterFactory adapterFactory) {
259: this .adapterFactory = adapterFactory;
260: }
261:
262: public boolean isSupported(String string, String string1) {
263: throw operationNotSupported();
264: }
265:
266: public Node appendChild(Node node) throws DOMException {
267: throw operationNotSupported();
268: }
269:
270: public Node cloneNode(boolean b) {
271: log.trace("cloneNode");
272: throw operationNotSupported();
273: }
274:
275: public boolean hasAttributes() {
276: return false;
277: }
278:
279: public boolean hasChildNodes() {
280: return false;
281: }
282:
283: public Node insertBefore(Node node, Node node1) throws DOMException {
284: throw operationNotSupported();
285: }
286:
287: public void normalize() {
288: log.trace("normalize");
289: throw operationNotSupported();
290: }
291:
292: public Node removeChild(Node node) throws DOMException {
293: throw operationNotSupported();
294: }
295:
296: public Node replaceChild(Node node, Node node1) throws DOMException {
297: throw operationNotSupported();
298: }
299:
300: // Begin DOM 3 methods
301:
302: public boolean isDefaultNamespace(String string) {
303: throw operationNotSupported();
304: }
305:
306: public String lookupNamespaceURI(String string) {
307: throw operationNotSupported();
308: }
309:
310: public String getNodeName() {
311: throw operationNotSupported();
312: }
313:
314: public short getNodeType() {
315: throw operationNotSupported();
316: }
317:
318: public String getBaseURI() {
319: throw operationNotSupported();
320: }
321:
322: public short compareDocumentPosition(Node node) throws DOMException {
323: throw operationNotSupported();
324: }
325:
326: public String getTextContent() throws DOMException {
327: throw operationNotSupported();
328: }
329:
330: public void setTextContent(String string) throws DOMException {
331: throw operationNotSupported();
332:
333: }
334:
335: public boolean isSameNode(Node node) {
336: throw operationNotSupported();
337: }
338:
339: public String lookupPrefix(String string) {
340: throw operationNotSupported();
341: }
342:
343: public boolean isEqualNode(Node node) {
344: throw operationNotSupported();
345: }
346:
347: public Object getFeature(String string, String string1) {
348: throw operationNotSupported();
349: }
350:
351: public Object setUserData(String string, Object object,
352: UserDataHandler userDataHandler) {
353: throw operationNotSupported();
354: }
355:
356: public Object getUserData(String string) {
357: throw operationNotSupported();
358: }
359:
360: // End node methods
361:
362: protected WebWorkException operationNotSupported() {
363: return new WebWorkException("Operation not supported.");
364: }
365:
366: public String toString() {
367: return getClass() + ": " + getNodeName() + " parent="
368: + getParentNode();
369: }
370: }
|