001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.xml2;
030:
031: import com.caucho.util.L10N;
032: import com.caucho.vfs.Depend;
033: import com.caucho.vfs.WriteStream;
034:
035: import org.w3c.dom.DOMException;
036: import org.w3c.dom.Document;
037: import org.w3c.dom.NamedNodeMap;
038: import org.w3c.dom.Node;
039: import org.w3c.dom.NodeList;
040: import org.w3c.dom.UserDataHandler;
041:
042: import javax.xml.namespace.QName;
043: import java.io.IOException;
044: import java.util.ArrayList;
045:
046: /**
047: * QAbstractNode is an abstract implementation for any DOM node.
048: */
049: public abstract class QAbstractNode implements CauchoNode,
050: java.io.Serializable {
051: protected static L10N L = new L10N(QAbstractNode.class);
052:
053: QDocument _owner;
054:
055: QNode _parent;
056:
057: QAbstractNode _next;
058: QAbstractNode _previous;
059:
060: String _systemId;
061: String _filename;
062: int _line;
063:
064: protected QAbstractNode() {
065: }
066:
067: protected QAbstractNode(QDocument owner) {
068: _owner = owner;
069: }
070:
071: public void setLocation(String systemId, String filename, int line,
072: int column) {
073: _systemId = systemId;
074: _filename = filename;
075: _line = line;
076: }
077:
078: /**
079: * Returns the node's source filename.
080: */
081: public String getFilename() {
082: if (_filename != null)
083: return _filename;
084: else if (_previous != null)
085: return _previous.getFilename();
086: else if (_parent != null)
087: return _parent.getFilename();
088: else
089: return null;
090: }
091:
092: /**
093: * Returns the base URI of the node.
094: */
095: public String getBaseURI() {
096: if (_systemId != null)
097: return _systemId;
098: else if (_previous != null)
099: return _previous.getBaseURI();
100: else if (_parent != null)
101: return _parent.getBaseURI();
102: else
103: return getFilename();
104: }
105:
106: /**
107: * Returns the base URI
108: */
109: public static String baseURI(Node node) {
110: if (node instanceof QAbstractNode)
111: return ((QAbstractNode) node).getBaseURI();
112: else
113: return null;
114: }
115:
116: /**
117: * Returns the node's source line.
118: */
119: public int getLine() {
120: if (_filename != null)
121: return _line;
122: else if (_previous != null)
123: return _previous.getLine();
124: else if (_parent != null)
125: return _parent.getLine();
126: else
127: return 0;
128: }
129:
130: public int getColumn() {
131: return 0;
132: }
133:
134: /**
135: * Returns the owning document.
136: */
137: public Document getOwnerDocument() {
138: return _owner;
139: }
140:
141: public boolean isSupported(String feature, String version) {
142: return _owner.getImplementation().hasFeature(feature, version);
143: }
144:
145: /**
146: * Returns a feature value.
147: */
148: public Object getFeature(String feature, String version) {
149: return null;
150: }
151:
152: /**
153: * Sets a feature value.
154: */
155: public void setFeature(String feature, boolean value) {
156: }
157:
158: /**
159: * Compares the document position
160: */
161: public short compareDocumentPosition(Node node) {
162: return 0;
163: }
164:
165: /**
166: * Looks up a prefix value.
167: */
168: public String lookupPrefix(String feature) {
169: return null;
170: }
171:
172: /**
173: * Returns true if the node has attributes.
174: */
175: public boolean hasAttributes() {
176: return false;
177: }
178:
179: public String getPrefix() {
180: return "";
181: }
182:
183: public void setPrefix(String prefix) {
184: }
185:
186: public Object setUserData(String key, Object value,
187: UserDataHandler userData) {
188: return null;
189: }
190:
191: public Object getUserData(String data) {
192: return null;
193: }
194:
195: public String getCanonicalName() {
196: return getNodeName();
197: }
198:
199: public String getLocalName() {
200: return getNodeName();
201: }
202:
203: public String getNamespaceURI() {
204: return "";
205: }
206:
207: public QName getQName() {
208: return new QName(getNodeName(), getNamespaceURI());
209: }
210:
211: public String getNodeValue() {
212: return null;
213: }
214:
215: public void setNodeValue(String value) {
216: }
217:
218: public Node getParentNode() {
219: return _parent;
220: }
221:
222: public NodeList getChildNodes() {
223: return new QEmptyNodeList();
224: }
225:
226: public Node getFirstChild() {
227: return null;
228: }
229:
230: public Node getLastChild() {
231: return null;
232: }
233:
234: public Node getPreviousSibling() {
235: return _previous;
236: }
237:
238: public Node getNextSibling() {
239: return _next;
240: }
241:
242: public NamedNodeMap getAttributes() {
243: return null;
244: }
245:
246: public Node insertBefore(Node newChild, Node refChild)
247: throws DOMException {
248: throw new QDOMException(DOMException.HIERARCHY_REQUEST_ERR, "");
249: }
250:
251: public Node replaceChild(Node newChild, Node refChild)
252: throws DOMException {
253: throw new QDOMException(DOMException.HIERARCHY_REQUEST_ERR, "");
254: }
255:
256: public Node removeChild(Node oldChild) throws DOMException {
257: throw new QDOMException(DOMException.HIERARCHY_REQUEST_ERR, "");
258: }
259:
260: public Node appendChild(Node newNode) throws DOMException {
261: throw new QDOMException(DOMException.HIERARCHY_REQUEST_ERR, "");
262: }
263:
264: public boolean hasChildNodes() {
265: return false;
266: }
267:
268: public boolean equals(Node arg, boolean deep) {
269: return this == arg;
270: }
271:
272: void remove() {
273: if (_owner != null)
274: _owner._changeCount++;
275:
276: if (_previous != null)
277: _previous._next = _next;
278: else if (_parent != null)
279: _parent._firstChild = _next;
280:
281: if (_next != null)
282: _next._previous = _previous;
283: else if (_parent != null)
284: _parent._lastChild = _previous;
285:
286: _previous = null;
287: _next = null;
288: _parent = null;
289: }
290:
291: public QAbstractNode getNextPreorder() {
292: if (_next != null)
293: return _next;
294:
295: for (QNode ptr = _parent; ptr != null; ptr = ptr._parent) {
296: if (ptr._next != null)
297: return ptr._next;
298: }
299:
300: return null;
301: }
302:
303: public boolean hasContent() {
304: return false;
305: }
306:
307: public QAbstractNode getNextContent() {
308: for (QAbstractNode node = _next; node != null; node = node._next) {
309: if (node.hasContent())
310: return node;
311: }
312:
313: return null;
314: }
315:
316: public QAbstractNode getPreviousContent() {
317: for (QAbstractNode node = _previous; node != null; node = node._previous) {
318: if (node.hasContent())
319: return node;
320: }
321:
322: return null;
323: }
324:
325: public String getTextValue() {
326: return getNodeValue();
327: }
328:
329: /**
330: * Support the same and the implementation
331: */
332: public boolean supports(String feature, String version) {
333: return _owner._implementation.hasFeature(feature, version);
334: }
335:
336: public void normalize() {
337:
338: }
339:
340: public Node cloneNode(boolean deep) {
341: return _owner.importNode(this , deep);
342: }
343:
344: // DOM level 3
345:
346: public short compareTreePosition(Node other) {
347: throw new UnsupportedOperationException();
348: }
349:
350: public String getTextContent() throws DOMException {
351: return XmlUtil.textValue(this );
352: }
353:
354: public void setTextContent(String textContent) throws DOMException {
355: throw new UnsupportedOperationException();
356: }
357:
358: public boolean isSameNode(Node other) {
359: return this == other;
360: }
361:
362: public String lookupNamespacePrefix(String namespaceURI,
363: boolean useDefault) {
364: throw new UnsupportedOperationException();
365: }
366:
367: public boolean isDefaultNamespace(String namespaceURI) {
368: throw new UnsupportedOperationException();
369: }
370:
371: public String lookupNamespaceURI(String prefix) {
372: throw new UnsupportedOperationException();
373: }
374:
375: public boolean isEqualNode(Node arg) {
376: return equals(arg);
377: }
378:
379: public Node getInterface(String feature) {
380: throw new UnsupportedOperationException();
381: }
382:
383: /*
384: public Object setUserData(String key,
385: Object data,
386: UserDataHandler handler)
387: {
388: throw new UnsupportedOperationException();
389: }
390:
391: public Object getUserData(String key)
392: {
393: throw new UnsupportedOperationException();
394: }
395: */
396:
397: // Caucho stuff
398: public ArrayList<Depend> getDependencyList() {
399: if (_owner != null)
400: return _owner.getDependencyList();
401: else
402: return null;
403: }
404:
405: boolean isNameValid(String name) {
406: if (name == null || name.length() == 0)
407: return false;
408:
409: if (!XmlChar.isNameStart(name.charAt(0)))
410: return false;
411:
412: for (int i = 1; i < name.length(); i++) {
413: char ch = name.charAt(i);
414: if (!XmlChar.isNameChar(ch))
415: return false;
416: }
417:
418: return true;
419: }
420:
421: public boolean checkValid() throws Exception {
422: if (_parent == null) {
423: if (_next != null || _previous != null)
424: throw new Exception("null bad: " + this );
425: else
426: return true;
427: }
428:
429: if (_parent._owner != _owner && _owner != _parent)
430: throw new Exception("owner bad: " + this );
431:
432: QAbstractNode ptr = _parent._firstChild;
433: for (; ptr != null && ptr != this ; ptr = ptr._next) {
434: }
435: if (ptr == null)
436: throw new Exception("not in parent: " + this );
437:
438: ptr = _parent._lastChild;
439: for (; ptr != null && ptr != this ; ptr = ptr._previous) {
440: }
441: if (ptr == null)
442: throw new Exception("not in parent: " + this );
443:
444: if (_next == null && _parent._lastChild != this )
445: throw new Exception("bad tail: " + this );
446:
447: else if (_next != null && _next._previous != this )
448: throw new Exception("bad link: " + this );
449:
450: if (_previous == null && _parent._firstChild != this )
451: throw new Exception("bad head: " + this );
452: else if (_previous != null && _previous._next != this )
453: throw new Exception("bad link: " + this );
454:
455: return true;
456: }
457:
458: void print(XmlPrinter out) throws IOException {
459: }
460:
461: public void print(WriteStream out) throws IOException {
462: new XmlPrinter(out).printXml(this );
463: }
464:
465: public void printPretty(WriteStream out) throws IOException {
466: new XmlPrinter(out).printPrettyXml(this );
467: }
468:
469: public void printHtml(WriteStream out) throws IOException {
470: new XmlPrinter(out).printHtml(this );
471: }
472:
473: private Object writeReplace() {
474: return new SerializedXml(this);
475: }
476: }
|