001: // Copyright (c) 2004, 2005 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.xml;
005:
006: import gnu.lists.*;
007: import gnu.xml.*; /* #ifdef use:org.w3c.dom.Node */// import org.w3c.dom.*;
008: /* #endif */
009:
010: import gnu.mapping.*;
011: import gnu.text.Path;
012:
013: public abstract class KNode extends SeqPosition implements
014: /* #ifdef use:org.w3c.dom.Node */
015: // org.w3c.dom.Node,
016: /* #endif */
017: Consumable {
018:
019: public KNode(NodeTree seq, int ipos) {
020: super (seq, ipos);
021: }
022:
023: public static Object atomicValue(Object value) {
024: if (value instanceof KNode) {
025: KNode node = (KNode) value;
026: return ((NodeTree) node.sequence).typedValue(node.ipos);
027: }
028: return value;
029: }
030:
031: /** Convert value to a KNode, returning null if it isn't a node. */
032: public static KNode coerce(Object value) {
033: if (value instanceof KNode)
034: return (KNode) value;
035: if (value instanceof NodeTree) {
036: NodeTree ntree = (NodeTree) value;
037: return make(ntree, ntree.startPos());
038: }
039: if (value instanceof SeqPosition
040: && !(value instanceof TreePosition)) {
041: SeqPosition seqp = (SeqPosition) value;
042: if (seqp.sequence instanceof NodeTree)
043: return make((NodeTree) seqp.sequence, seqp.ipos);
044: }
045: return null;
046: }
047:
048: public static KNode make(NodeTree seq, int ipos) {
049: int index = seq.posToDataIndex(ipos);
050: while (index < seq.data.length
051: && seq.data[index] == TreeList.BEGIN_ENTITY) {
052: index += TreeList.BEGIN_ENTITY_SIZE;
053: if (index == seq.gapStart)
054: index = seq.gapEnd;
055: ipos = index << 1;
056: }
057: int kind = seq.getNextKindI(seq.posToDataIndex(ipos));
058: switch (kind) {
059: case Sequence.ELEMENT_VALUE:
060: return new KElement(seq, ipos);
061: case Sequence.ATTRIBUTE_VALUE:
062: return new KAttr(seq, ipos);
063: case Sequence.DOCUMENT_VALUE:
064: return new KDocument(seq, ipos);
065: case Sequence.CDATA_VALUE:
066: return new KCDATASection(seq, ipos);
067: case Sequence.COMMENT_VALUE:
068: return new KComment(seq, ipos);
069: case Sequence.PROCESSING_INSTRUCTION_VALUE:
070: return new KProcessingInstruction(seq, ipos);
071: case Sequence.EOF_VALUE:
072: if (!seq.isEmpty())
073: return null;
074: // .. else fall through to create an empty text node.
075: default:
076: return new KText(seq, ipos);
077: }
078: }
079:
080: /* #ifdef JAVA5 */
081: // public KNode copy ()
082: // {
083: // return make((NodeTree) sequence, sequence.copyPos(getPos()));
084: // }
085: /* #else */
086: public SeqPosition copy() {
087: return make((NodeTree) sequence, sequence.copyPos(getPos()));
088: }
089:
090: /* #endif */
091:
092: public static KNode make(NodeTree seq) {
093: return make(seq, 0);
094: }
095:
096: public boolean isSupported(String feature, String version) {
097: return false;
098: }
099:
100: /* #ifdef use:org.w3c.dom.Node */
101: // public abstract short getNodeType ();
102: /* #endif */
103:
104: public String getNodeName() {
105: return sequence.getNextTypeName(ipos);
106: }
107:
108: /** The Data Model's node-name accessor.
109: * Return the node's name as a SSymbol (QName) or null if there is none.
110: */
111: public Symbol getNodeSymbol() {
112: Object type = ((NodeTree) sequence).getNextTypeObject(ipos);
113: if (type == null)
114: return null;
115: if (type instanceof Symbol)
116: return (Symbol) type;
117: return Namespace.EmptyNamespace.getSymbol(type.toString()
118: .intern());
119: }
120:
121: /** Get the raw "type object" of a node.
122: */
123: public Object getNodeNameObject() {
124: return ((NodeTree) sequence).getNextTypeObject(ipos);
125: }
126:
127: public String getNamespaceURI() {
128: return ((NodeTree) sequence).posNamespaceURI(ipos);
129: }
130:
131: public String getPrefix() {
132: return ((NodeTree) sequence).posPrefix(ipos);
133: }
134:
135: public String getLocalName() {
136: return ((NodeTree) sequence).posLocalName(ipos);
137: }
138:
139: public static String getNodeValue(NodeTree seq, int ipos) {
140: StringBuffer sbuf = new StringBuffer();
141: getNodeValue(seq, ipos, sbuf);
142: return sbuf.toString();
143: }
144:
145: public static void getNodeValue(NodeTree seq, int ipos,
146: StringBuffer sbuf) {
147: seq.stringValue(seq.posToDataIndex(ipos), sbuf);
148: }
149:
150: public String getNodeValue() {
151: StringBuffer sbuf = new StringBuffer();
152: getNodeValue(sbuf);
153: return sbuf.toString();
154: }
155:
156: public void getNodeValue(StringBuffer sbuf) {
157: getNodeValue((NodeTree) sequence, ipos, sbuf);
158: }
159:
160: public boolean hasChildNodes() {
161: return ((NodeTree) sequence).posFirstChild(ipos) >= 0;
162: }
163:
164: public String getTextContent() {
165: StringBuffer sbuf = new StringBuffer();
166: getTextContent(sbuf);
167: return sbuf.toString();
168: }
169:
170: protected void getTextContent(StringBuffer sbuf) {
171: // What is the difference between getTextContent and getNodeValue? FIXME.
172: getNodeValue(sbuf);
173: }
174:
175: /* #ifdef use:org.w3c.dom.Node */
176: // public Node getParentNode()
177: // {
178: // int parent = sequence.parentPos(ipos);
179: // if (parent == -1)
180: // return null;
181: // return make((NodeTree) sequence, parent);
182: // }
183: // public Node getPreviousSibling ()
184: // {
185: // int parent = sequence.parentPos(ipos);
186: // if (parent == -1)
187: // parent = 0;
188: // int index = ((NodeTree) sequence).posToDataIndex(ipos);
189: // int child = sequence.firstChildPos(parent);
190: // int previous = 0;
191: // for (;;)
192: // {
193: // previous = child;
194: // child = sequence.nextPos(child);
195: // if (child == 0)
196: // break;
197: // if (((NodeTree) sequence).posToDataIndex(child) == index)
198: // break;
199: // }
200: // return previous == 0 ? null
201: // : make((NodeTree) sequence, previous);
202: // }
203: /* #endif */
204:
205: /* #ifdef use:org.w3c.dom.Node */
206: // public Node getNextSibling ()
207: // {
208: // int next = ((NodeTree) sequence).nextPos(ipos);
209: // return next == 0 ? null
210: // : make((NodeTree) sequence, next);
211: // }
212: // public Node getFirstChild()
213: // {
214: // int child = ((NodeTree) sequence).posFirstChild(ipos);
215: // return make((NodeTree) sequence, child);
216: // }
217: // public Node getLastChild()
218: // {
219: // int last = 0;
220: // int child = sequence.firstChildPos(ipos);
221: // while (child != 0)
222: // {
223: // last = child;
224: // child = sequence.nextPos(child);
225: // }
226: // return last == 0 ? null : make((NodeTree) sequence, last);
227: // }
228: // public NodeList getChildNodes ()
229: // {
230: // Nodes nodes = new SortedNodes();
231: // int child = sequence.firstChildPos(ipos);
232: // while (child != 0)
233: // {
234: // nodes.writePosition(sequence, child);
235: // child = sequence.nextPos(child);
236: // }
237: // return nodes;
238: // }
239: // /** Not implemented yet. */
240: // public NodeList getElementsByTagName(String tagname)
241: // {
242: // throw new UnsupportedOperationException("getElementsByTagName not implemented yet");
243: // /*
244: // Nodes nodes = new SortedNodes();
245: // int child = sequence.firstChildPos(ipos);
246: // while (child != 0)
247: // {
248: // if (matches)
249: // nodes.writePosition(sequence, child);
250: // child = sequence.nextPos(child);
251: // }
252: // return nodes;
253: // */
254: // }
255: /* #endif */
256:
257: /* #ifdef use:org.w3c.dom.Node */
258: // /** Not implemented. */
259: // public void setNodeValue (String nodeValue) throws DOMException
260: // {
261: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
262: // "setNodeValue not supported");
263: // }
264: // /** Not implemented. */
265: // public void setPrefix (String prefix) throws DOMException
266: // {
267: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
268: // "setPrefix not supported");
269: // }
270: // /** Not implemented. */
271: // public Node insertBefore(Node newChild, Node refChild)
272: // throws DOMException
273: // {
274: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
275: // "insertBefore not supported");
276: // }
277: // /** Not implemented. */
278: // public Node replaceChild(Node newChild, Node oldChild)
279: // throws DOMException
280: // {
281: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
282: // "replaceChild not supported");
283: // }
284: // /** Not implemented. */
285: // public Node removeChild(Node oldChild)
286: // throws DOMException
287: // {
288: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
289: // "removeChild not supported");
290: // }
291: // /** Not implemented. */
292: // public Node appendChild(Node newChild)
293: // throws DOMException
294: // {
295: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
296: // "appendChild not supported");
297: // }
298: // /** Not implemented. */
299: // public void setTextContent (String textContent)
300: // throws DOMException
301: // {
302: // throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
303: // "setTextContent not supported");
304: // }
305: // /** Only implemented if deep is true. */
306: // public Node cloneNode(boolean deep)
307: // {
308: // if (! deep)
309: // throw new UnsupportedOperationException("shallow cloneNode not implemented");
310: // NodeTree tree = new NodeTree();
311: // ((NodeTree) sequence).consumeNext(ipos, tree);
312: // return make(tree);
313: // }
314: // public org.w3c.dom.Document getOwnerDocument ()
315: // {
316: // int kind = sequence.getNextKind(ipos);
317: // if (kind == Sequence.DOCUMENT_VALUE)
318: // return new KDocument((NodeTree) sequence, 0);
319: // return null;
320: // }
321: // public NamedNodeMap getAttributes ()
322: // {
323: // throw new UnsupportedOperationException("getAttributes not implemented yet");
324: // }
325: /* #endif */
326:
327: public void normalize() {
328: }
329:
330: public boolean hasAttributes() {
331: return false;
332: }
333:
334: public boolean isDefaultNamespace(String namespaceURI) {
335: return ((NodeTree) sequence).posIsDefaultNamespace(ipos,
336: namespaceURI);
337: }
338:
339: public String lookupNamespaceURI(String prefix) {
340: return ((NodeTree) sequence)
341: .posLookupNamespaceURI(ipos, prefix);
342: }
343:
344: public String lookupPrefix(String namespaceURI) {
345: return ((NodeTree) sequence)
346: .posLookupPrefix(ipos, namespaceURI);
347: }
348:
349: public String getBaseURI() {
350: Object uri = ((NodeTree) sequence).baseUriOfPos(ipos, true);
351: return uri == null ? null : uri.toString();
352: }
353:
354: public Path baseURI() {
355: return ((NodeTree) sequence).baseUriOfPos(ipos, true);
356: }
357:
358: /* #ifdef use:org.w3c.dom.Node */
359: // public short compareDocumentPosition (Node other)
360: // throws DOMException
361: // {
362: // if (! (other instanceof KNode))
363: // throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
364: // "other Node is a "+other.getClass().getName());
365: // KNode n = (KNode) other;
366: // AbstractSequence nseq = n.sequence;
367: // return (short) (sequence == nseq ? nseq.compare(ipos, n.ipos)
368: // : (int) sequence.stableCompare(nseq));
369: // }
370: //
371: // public boolean isSameNode (Node node)
372: // {
373: // if (! (node instanceof KNode))
374: // return false;
375: // KNode n = (KNode) node;
376: // if (sequence != n.sequence)
377: // return false;
378: // return sequence.equals(ipos, n.ipos);
379: // }
380: // public boolean isEqualNode (Node node)
381: // {
382: // throw new UnsupportedOperationException("getAttributesisEqualNode not implemented yet");
383: // }
384: /* #endif */
385:
386: public String toString() {
387: CharArrayOutPort wr = new CharArrayOutPort();
388: XMLPrinter xp = new XMLPrinter(wr);
389: ((NodeTree) sequence).consumeNext(ipos, xp);
390: xp.close();
391: wr.close();
392: return wr.toString();
393: }
394:
395: public Object getFeature(String feature, String version) {
396: return null;
397: }
398:
399: public void consume(Consumer out) {
400: if (out instanceof PositionConsumer)
401: ((PositionConsumer) out).consume(this );
402: else
403: ((NodeTree) sequence).consumeNext(ipos, out);
404: }
405:
406: /* #ifdef JAXP-1.3 */
407: // public Object setUserData (String key, Object data, UserDataHandler handler)
408: // {
409: // throw new UnsupportedOperationException("setUserData not implemented yet");
410: // }
411: // public Object getUserData (String key)
412: // {
413: // return null;
414: // }
415: /* #endif JAXP-1.3 */
416: }
|