cbba266c4a23fb527765556b615050c64295052d
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / tidy / DOMNodeImpl.java
1 /*
2  * @(#)DOMNodeImpl.java   1.11 2000/08/16
3  *
4  */
5
6 package net.sourceforge.phpdt.tidy;
7
8 import org.w3c.dom.DOMException;
9
10 /**
11  *
12  * DOMNodeImpl
13  *
14  * (c) 1998-2000 (W3C) MIT, INRIA, Keio University
15  * See Tidy.java for the copyright notice.
16  * Derived from <a href="http://www.w3.org/People/Raggett/tidy">
17  * HTML Tidy Release 4 Aug 2000</a>
18  *
19  * @author  Dave Raggett <dsr@w3.org>
20  * @author  Andy Quick <ac.quick@sympatico.ca> (translation to Java)
21  * @version 1.4, 1999/09/04 DOM Support
22  * @version 1.5, 1999/10/23 Tidy Release 27 Sep 1999
23  * @version 1.6, 1999/11/01 Tidy Release 22 Oct 1999
24  * @version 1.7, 1999/12/06 Tidy Release 30 Nov 1999
25  * @version 1.8, 2000/01/22 Tidy Release 13 Jan 2000
26  * @version 1.9, 2000/06/03 Tidy Release 30 Apr 2000
27  * @version 1.10, 2000/07/22 Tidy Release 8 Jul 2000
28  * @version 1.11, 2000/08/16 Tidy Release 4 Aug 2000
29  */
30
31 public class DOMNodeImpl implements org.w3c.dom.Node {
32
33     protected Node adaptee;
34
35     protected DOMNodeImpl(Node adaptee)
36     {
37         this.adaptee = adaptee;
38     }
39
40
41     /* --------------------- DOM ---------------------------- */
42
43     /**
44      * @see org.w3c.dom.Node#getNodeValue
45      */
46     public String getNodeValue() throws DOMException
47     {
48         String value = ""; //BAK 10/10/2000 replaced null
49         if (adaptee.type == Node.TextNode ||
50             adaptee.type == Node.CDATATag ||
51             adaptee.type == Node.CommentTag ||
52             adaptee.type == Node.ProcInsTag)
53         {
54
55             if (adaptee.textarray != null && adaptee.start < adaptee.end)
56             {
57                 value = Lexer.getString(adaptee.textarray,
58                                         adaptee.start,
59                                         adaptee.end - adaptee.start);
60             }
61         }
62         return value;
63     }
64
65     /**
66      * @see org.w3c.dom.Node#setNodeValue
67      */
68     public void setNodeValue(String nodeValue) throws DOMException
69     {
70         if (adaptee.type == Node.TextNode ||
71             adaptee.type == Node.CDATATag ||
72             adaptee.type == Node.CommentTag ||
73             adaptee.type == Node.ProcInsTag)
74         {
75             byte[] textarray = Lexer.getBytes(nodeValue);
76             adaptee.textarray = textarray;
77             adaptee.start = 0;
78             adaptee.end = textarray.length;
79         }
80     }
81
82     /**
83      * @see org.w3c.dom.Node#getNodeName
84      */
85     public String getNodeName()
86     {
87         return adaptee.element;
88     }
89
90     /**
91      * @see org.w3c.dom.Node#getNodeType
92      */
93     public short getNodeType()
94     {
95         short result = -1;
96         switch (adaptee.type) {
97         case Node.RootNode:
98             result = org.w3c.dom.Node.DOCUMENT_NODE;
99             break;
100         case Node.DocTypeTag:
101             result = org.w3c.dom.Node.DOCUMENT_TYPE_NODE;
102             break;
103         case Node.CommentTag:
104             result = org.w3c.dom.Node.COMMENT_NODE;
105             break;
106         case Node.ProcInsTag:
107             result = org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE;
108             break;
109         case Node.TextNode:
110             result = org.w3c.dom.Node.TEXT_NODE;
111             break;
112         case Node.CDATATag:
113             result = org.w3c.dom.Node.CDATA_SECTION_NODE;
114             break;
115         case Node.StartTag:
116         case Node.StartEndTag:
117             result = org.w3c.dom.Node.ELEMENT_NODE;
118             break;
119         }
120         return result;
121     }
122
123     /**
124      * @see org.w3c.dom.Node#getParentNode
125      */
126     public org.w3c.dom.Node getParentNode()
127     {
128         if (adaptee.parent != null)
129             return adaptee.parent.getAdapter();
130         else
131             return null;
132     }
133
134     /**
135      * @see org.w3c.dom.Node#getChildNodes
136      */
137     public org.w3c.dom.NodeList getChildNodes()
138     {
139         return new DOMNodeListImpl(adaptee);
140     }
141
142     /**
143      * @see org.w3c.dom.Node#getFirstChild
144      */
145     public org.w3c.dom.Node getFirstChild()
146     {
147         if (adaptee.content != null)
148             return adaptee.content.getAdapter();
149         else
150             return null;
151     }
152
153     /**
154      * @see org.w3c.dom.Node#getLastChild
155      */
156     public org.w3c.dom.Node getLastChild()
157     {
158         if (adaptee.last != null)
159             return adaptee.last.getAdapter();
160         else
161             return null;
162     }
163
164     /**
165      * @see org.w3c.dom.Node#getPreviousSibling
166      */
167     public org.w3c.dom.Node getPreviousSibling()
168     {
169         if (adaptee.prev != null)
170             return adaptee.prev.getAdapter();
171         else
172             return null;
173     }
174
175     /**
176      * @see org.w3c.dom.Node#getNextSibling
177      */
178     public org.w3c.dom.Node getNextSibling()
179     {
180         if (adaptee.next != null)
181             return adaptee.next.getAdapter();
182         else
183             return null;
184     }
185
186     /**
187      * @see org.w3c.dom.Node#getAttributes
188      */
189     public org.w3c.dom.NamedNodeMap getAttributes()
190     {
191         return new DOMAttrMapImpl(adaptee.attributes);
192     }
193
194     /**
195      * @see org.w3c.dom.Node#getOwnerDocument
196      */
197     public org.w3c.dom.Document getOwnerDocument()
198     {
199         Node node;
200
201         node = this.adaptee;
202         if (node != null && node.type == Node.RootNode)
203             return null;
204
205         for (node = this.adaptee;
206             node != null && node.type != Node.RootNode; node = node.parent);
207
208         if (node != null)
209             return (org.w3c.dom.Document)node.getAdapter();
210         else
211             return null;
212     }
213
214     /**
215      * @see org.w3c.dom.Node#insertBefore
216      */
217     public org.w3c.dom.Node insertBefore(org.w3c.dom.Node newChild,
218                                          org.w3c.dom.Node refChild)
219                                              throws DOMException
220     {
221         // TODO - handle newChild already in tree
222
223         if (newChild == null)
224             return null;
225         if (!(newChild instanceof DOMNodeImpl)) {
226             throw new DOMExceptionImpl(DOMException.WRONG_DOCUMENT_ERR,
227                                        "newChild not instanceof DOMNodeImpl");
228         }
229         DOMNodeImpl newCh = (DOMNodeImpl)newChild;
230
231         if (this.adaptee.type == Node.RootNode) {
232             if (newCh.adaptee.type != Node.DocTypeTag &&
233                 newCh.adaptee.type != Node.ProcInsTag) {
234                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
235                                        "newChild cannot be a child of this node");
236             }
237         } else if (this.adaptee.type == Node.StartTag) {
238             if (newCh.adaptee.type != Node.StartTag &&
239                 newCh.adaptee.type != Node.StartEndTag &&
240                 newCh.adaptee.type != Node.CommentTag &&
241                 newCh.adaptee.type != Node.TextNode &&
242                 newCh.adaptee.type != Node.CDATATag) {
243                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
244                                        "newChild cannot be a child of this node");
245             }
246         }
247         if (refChild == null) {
248             Node.insertNodeAtEnd(this.adaptee, newCh.adaptee);
249             if (this.adaptee.type == Node.StartEndTag) {
250               this.adaptee.setType(Node.StartTag);
251             }
252         } else {
253             Node ref = this.adaptee.content;
254             while (ref != null) {
255                 if (ref.getAdapter() == refChild) break;
256                 ref = ref.next;
257             }
258             if (ref == null) {
259                 throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
260                                            "refChild not found");
261             }
262             Node.insertNodeBeforeElement(ref, newCh.adaptee);
263         }
264         return newChild;
265     }
266
267     /**
268      * @see org.w3c.dom.Node#replaceChild
269      */
270     public org.w3c.dom.Node replaceChild(org.w3c.dom.Node newChild,
271                                          org.w3c.dom.Node oldChild)
272                                              throws DOMException
273     {
274         // TODO - handle newChild already in tree
275
276         if (newChild == null)
277             return null;
278         if (!(newChild instanceof DOMNodeImpl)) {
279             throw new DOMExceptionImpl(DOMException.WRONG_DOCUMENT_ERR,
280                                        "newChild not instanceof DOMNodeImpl");
281         }
282         DOMNodeImpl newCh = (DOMNodeImpl)newChild;
283
284         if (this.adaptee.type == Node.RootNode) {
285             if (newCh.adaptee.type != Node.DocTypeTag &&
286                 newCh.adaptee.type != Node.ProcInsTag) {
287                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
288                                        "newChild cannot be a child of this node");
289             }
290         } else if (this.adaptee.type == Node.StartTag) {
291             if (newCh.adaptee.type != Node.StartTag &&
292                 newCh.adaptee.type != Node.StartEndTag &&
293                 newCh.adaptee.type != Node.CommentTag &&
294                 newCh.adaptee.type != Node.TextNode &&
295                 newCh.adaptee.type != Node.CDATATag) {
296                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
297                                        "newChild cannot be a child of this node");
298             }
299         }
300         if (oldChild == null) {
301             throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
302                                        "oldChild not found");
303         } else {
304             Node n;
305             Node ref = this.adaptee.content;
306             while (ref != null) {
307                 if (ref.getAdapter() == oldChild) break;
308                 ref = ref.next;
309             }
310             if (ref == null) {
311                 throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
312                                            "oldChild not found");
313             }
314             newCh.adaptee.next = ref.next;
315             newCh.adaptee.prev = ref.prev;
316             newCh.adaptee.last = ref.last;
317             newCh.adaptee.parent = ref.parent;
318             newCh.adaptee.content = ref.content;
319             if (ref.parent != null) {
320                 if (ref.parent.content == ref)
321                     ref.parent.content = newCh.adaptee;
322                 if (ref.parent.last == ref)
323                     ref.parent.last = newCh.adaptee;
324             }
325             if (ref.prev != null) {
326                 ref.prev.next = newCh.adaptee;
327             }
328             if (ref.next != null) {
329                 ref.next.prev = newCh.adaptee;
330             }
331             for (n = ref.content; n != null; n = n.next) {
332                 if (n.parent == ref)
333                     n.parent = newCh.adaptee;
334             }
335         }
336         return oldChild;
337     }
338
339     /**
340      * @see org.w3c.dom.Node#removeChild
341      */
342     public org.w3c.dom.Node removeChild(org.w3c.dom.Node oldChild)
343                                             throws DOMException
344     {
345         if (oldChild == null)
346             return null;
347
348         Node ref = this.adaptee.content;
349         while (ref != null) {
350             if (ref.getAdapter() == oldChild) break;
351             ref = ref.next;
352         }
353         if (ref == null) {
354             throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
355                                        "refChild not found");
356         }
357         Node.discardElement(ref);
358
359         if (this.adaptee.content == null
360         &&  this.adaptee.type == Node.StartTag) {
361           this.adaptee.setType(Node.StartEndTag);
362         }
363
364         return oldChild;
365     }
366
367     /**
368      * @see org.w3c.dom.Node#appendChild
369      */
370     public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild)
371                                             throws DOMException
372     {
373         // TODO - handle newChild already in tree
374
375         if (newChild == null)
376             return null;
377         if (!(newChild instanceof DOMNodeImpl)) {
378             throw new DOMExceptionImpl(DOMException.WRONG_DOCUMENT_ERR,
379                                        "newChild not instanceof DOMNodeImpl");
380         }
381         DOMNodeImpl newCh = (DOMNodeImpl)newChild;
382
383         if (this.adaptee.type == Node.RootNode) {
384             if (newCh.adaptee.type != Node.DocTypeTag &&
385                 newCh.adaptee.type != Node.ProcInsTag) {
386                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
387                                        "newChild cannot be a child of this node");
388             }
389         } else if (this.adaptee.type == Node.StartTag) {
390             if (newCh.adaptee.type != Node.StartTag &&
391                 newCh.adaptee.type != Node.StartEndTag &&
392                 newCh.adaptee.type != Node.CommentTag &&
393                 newCh.adaptee.type != Node.TextNode &&
394                 newCh.adaptee.type != Node.CDATATag) {
395                 throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
396                                        "newChild cannot be a child of this node");
397             }
398         }
399         Node.insertNodeAtEnd(this.adaptee, newCh.adaptee);
400
401         if (this.adaptee.type == Node.StartEndTag) {
402           this.adaptee.setType(Node.StartTag);
403         }
404
405         return newChild;
406     }
407
408     /**
409      * @see org.w3c.dom.Node#hasChildNodes
410      */
411     public boolean hasChildNodes()
412     {
413         return (adaptee.content != null);
414     }
415
416     /**
417      * @see org.w3c.dom.Node#cloneNode
418      */
419     public org.w3c.dom.Node cloneNode(boolean deep)
420     {
421         Node node = adaptee.cloneNode(deep);
422         node.parent = null;
423         return node.getAdapter();
424     }
425
426     /**
427      * DOM2 - not implemented.
428      */
429     public void normalize()
430     {
431     }
432
433     /**
434      * DOM2 - not implemented.
435      */
436     public boolean supports(String feature, String version)
437     {
438         return isSupported(feature, version);
439     }
440
441     /**
442      * DOM2 - not implemented.
443      */
444     public String getNamespaceURI()
445     {
446         return null;
447     }
448
449     /**
450      * DOM2 - not implemented.
451      */
452     public String getPrefix()
453     {
454         return null;
455     }
456
457     /**
458      * DOM2 - not implemented.
459      */
460     public void setPrefix(String prefix)
461                             throws DOMException
462     {
463     }
464
465     /**
466      * DOM2 - not implemented.
467      */
468     public String getLocalName()
469     {
470       return null;
471     }
472
473     /**
474      * DOM2 - not implemented.
475      */
476     public boolean isSupported(String feature,String version) {
477         return false;
478     }
479
480     /**
481      * DOM2 - @see org.w3c.dom.Node#hasAttributes
482      * contributed by dlp@users.sourceforge.net
483      */
484     public boolean hasAttributes()
485     {
486         return adaptee.attributes != null;
487     }
488 }