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