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