KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > dom > AbstractElement


1 /*
2
3    Copyright 2000-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.dom;
19
20 import java.io.Serializable JavaDoc;
21
22 import org.apache.batik.dom.util.DOMUtilities;
23 import org.w3c.dom.Attr JavaDoc;
24 import org.w3c.dom.DOMException JavaDoc;
25 import org.w3c.dom.Element JavaDoc;
26 import org.w3c.dom.NamedNodeMap JavaDoc;
27 import org.w3c.dom.Node JavaDoc;
28 import org.w3c.dom.events.DocumentEvent JavaDoc;
29 import org.w3c.dom.events.MutationEvent JavaDoc;
30
31 /**
32  * This class implements the {@link org.w3c.dom.Element} interface.
33  *
34  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
35  * @version $Id: AbstractElement.java,v 1.29 2005/03/27 08:58:32 cam Exp $
36  */

37 public abstract class AbstractElement
38     extends AbstractParentChildNode
39     implements Element JavaDoc {
40
41     /**
42      * The attributes of this element.
43      */

44     protected NamedNodeMap JavaDoc attributes;
45
46     /**
47      * Creates a new AbstractElement object.
48      */

49     protected AbstractElement() {
50     }
51
52     /**
53      * Creates a new AbstractElement object.
54      * @param name The element name for validation purposes.
55      * @param owner The owner document.
56      * @exception DOMException
57      * INVALID_CHARACTER_ERR: if name contains invalid characters,
58      */

59     protected AbstractElement(String JavaDoc name, AbstractDocument owner) {
60     ownerDocument = owner;
61     if (!DOMUtilities.isValidName(name)) {
62         throw createDOMException(DOMException.INVALID_CHARACTER_ERR,
63                      "xml.name",
64                      new Object JavaDoc[] { name });
65     }
66     }
67
68     /**
69      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNodeType()}.
70      * @return {@link org.w3c.dom.Node#ELEMENT_NODE}
71      */

72     public short getNodeType() {
73     return ELEMENT_NODE;
74     }
75
76     /**
77      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#hasAttributes()}.
78      */

79     public boolean hasAttributes() {
80     return attributes != null && attributes.getLength() != 0;
81     }
82
83     /**
84      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getAttributes()}.
85      */

86     public NamedNodeMap JavaDoc getAttributes() {
87     return (attributes == null)
88             ? attributes = createAttributes()
89             : attributes;
90     }
91
92     /**
93      * <b>DOM</b>: Implements {@link org.w3c.dom.Element#getTagName()}.
94      * @return {@link #getNodeName()}.
95      */

96     public String JavaDoc getTagName() {
97     return getNodeName();
98     }
99
100     /**
101      * <b>DOM</b>: Implements {@link org.w3c.dom.Element#hasAttribute(String)}.
102      */

103     public boolean hasAttribute(String JavaDoc name) {
104     return attributes != null && attributes.getNamedItem(name) != null;
105     }
106
107     /**
108      * <b>DOM</b>: Implements {@link org.w3c.dom.Element#getAttribute(String)}.
109      */

110     public String JavaDoc getAttribute(String JavaDoc name) {
111     if (attributes == null) {
112         return "";
113     }
114     Attr JavaDoc attr = (Attr JavaDoc)attributes.getNamedItem(name);
115     return (attr == null) ? "" : attr.getValue();
116     }
117
118     /**
119      * <b>DOM</b>: Implements {@link
120      * org.w3c.dom.Element#setAttribute(String,String)}.
121      */

122     public void setAttribute(String JavaDoc name, String JavaDoc value) throws DOMException JavaDoc {
123     if (attributes == null) {
124         attributes = createAttributes();
125     }
126         Attr JavaDoc attr = getAttributeNode(name);
127         if (attr == null) {
128             attr = getOwnerDocument().createAttribute(name);
129             attr.setValue(value);
130             attributes.setNamedItem(attr);
131         } else {
132             attr.setValue(value);
133         }
134     }
135
136     /**
137      * <b>DOM</b>: Implements {@link
138      * org.w3c.dom.Element#removeAttribute(String)}.
139      */

140     public void removeAttribute(String JavaDoc name) throws DOMException JavaDoc {
141     if (!hasAttribute(name)) {
142             return;
143     }
144     attributes.removeNamedItem(name);
145     }
146
147     /**
148      * <b>DOM</b>: Implements {@link
149      * org.w3c.dom.Element#getAttributeNode(String)}.
150      */

151     public Attr JavaDoc getAttributeNode(String JavaDoc name) {
152     if (attributes == null) {
153         return null;
154     }
155     return (Attr JavaDoc)attributes.getNamedItem(name);
156     }
157
158     /**
159      * <b>DOM</b>: Implements {@link
160      * org.w3c.dom.Element#setAttributeNode(Attr)}.
161      */

162     public Attr JavaDoc setAttributeNode(Attr JavaDoc newAttr) throws DOMException JavaDoc {
163     if (newAttr == null) {
164         return null;
165     }
166     if (attributes == null) {
167         attributes = createAttributes();
168     }
169     return (Attr JavaDoc)attributes.setNamedItemNS(newAttr);
170     }
171
172     /**
173      * <b>DOM</b>: Implements {@link
174      * org.w3c.dom.Element#removeAttributeNode(Attr)}.
175      */

176     public Attr JavaDoc removeAttributeNode(Attr JavaDoc oldAttr) throws DOMException JavaDoc {
177     if (oldAttr == null) {
178         return null;
179     }
180     if (attributes == null) {
181         throw createDOMException(DOMException.NOT_FOUND_ERR,
182                      "attribute.missing",
183                      new Object JavaDoc[] { oldAttr.getName() });
184     }
185         String JavaDoc nsURI = oldAttr.getNamespaceURI();
186     return (Attr JavaDoc)attributes.removeNamedItemNS(nsURI,
187                                                   (nsURI==null
188                                                    ? oldAttr.getNodeName()
189                                                    : oldAttr.getLocalName()));
190     }
191
192     /**
193      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#normalize()}.
194      */

195     public void normalize() {
196     super.normalize();
197     if (attributes != null) {
198         NamedNodeMap JavaDoc map = getAttributes();
199         for (int i = map.getLength() - 1; i >= 0; i--) {
200         map.item(i).normalize();
201         }
202     }
203     }
204
205     /**
206      * <b>DOM</b>: Implements {@link
207      * org.w3c.dom.Element#hasAttributeNS(String,String)}.
208      */

209     public boolean hasAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
210     return attributes != null &&
211            attributes.getNamedItemNS(namespaceURI, localName) != null;
212     }
213
214     /**
215      * <b>DOM</b>: Implements {@link
216      * org.w3c.dom.Element#getAttributeNS(String,String)}.
217      */

218     public String JavaDoc getAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
219     if (attributes == null) {
220         return "";
221     }
222     Attr JavaDoc attr = (Attr JavaDoc)attributes.getNamedItemNS(namespaceURI, localName);
223     return (attr == null) ? "" : attr.getValue();
224     }
225
226     /**
227      * <b>DOM</b>: Implements {@link
228      * org.w3c.dom.Element#setAttributeNS(String,String,String)}.
229      */

230     public void setAttributeNS(String JavaDoc namespaceURI,
231                    String JavaDoc qualifiedName,
232                    String JavaDoc value) throws DOMException JavaDoc {
233     if (attributes == null) {
234         attributes = createAttributes();
235     }
236         Attr JavaDoc attr = getAttributeNodeNS(namespaceURI, qualifiedName);
237         if (attr == null) {
238             attr = getOwnerDocument().createAttributeNS(namespaceURI,
239                                                         qualifiedName);
240             attr.setValue(value);
241             attributes.setNamedItemNS(attr);
242         } else {
243             attr.setValue(value);
244         }
245     }
246
247     /**
248      * <b>DOM</b>: Implements {@link
249      * org.w3c.dom.Element#removeAttributeNS(String,String)}.
250      */

251     public void removeAttributeNS(String JavaDoc namespaceURI,
252                   String JavaDoc localName) throws DOMException JavaDoc {
253     if (!hasAttributeNS(namespaceURI, localName)) {
254             return;
255     }
256     attributes.removeNamedItemNS(namespaceURI, localName);
257     }
258
259     /**
260      * <b>DOM</b>: Implements {@link
261      * org.w3c.dom.Element#getAttributeNodeNS(String,String)}.
262      */

263     public Attr JavaDoc getAttributeNodeNS(String JavaDoc namespaceURI,
264                    String JavaDoc localName) {
265     if (attributes == null) {
266         return null;
267     }
268     return (Attr JavaDoc)attributes.getNamedItemNS(namespaceURI, localName);
269     }
270
271     /**
272      * <b>DOM</b>: Implements {@link
273      * org.w3c.dom.Element#setAttributeNodeNS(Attr)}.
274      */

275     public Attr JavaDoc setAttributeNodeNS(Attr JavaDoc newAttr) throws DOMException JavaDoc {
276     if (newAttr == null) {
277         return null;
278     }
279     if (attributes == null) {
280         attributes = createAttributes();
281     }
282     return (Attr JavaDoc)attributes.setNamedItemNS(newAttr);
283     }
284
285     /**
286      * Called when a child node has been added.
287      */

288     protected void nodeAdded(Node JavaDoc node) {
289         invalidateElementsByTagName(node);
290     }
291
292     /**
293      * Called when a child node is going to be removed.
294      */

295     protected void nodeToBeRemoved(Node JavaDoc node) {
296         invalidateElementsByTagName(node);
297     }
298
299     /**
300      * Invalidates the ElementsByTagName objects of this node and its parents.
301      */

302     private void invalidateElementsByTagName(Node JavaDoc node) {
303         if (node.getNodeType() != ELEMENT_NODE) {
304             return;
305         }
306         AbstractDocument ad = getCurrentDocument();
307         String JavaDoc ns = node.getNamespaceURI();
308         String JavaDoc nm = node.getNodeName();
309         String JavaDoc ln = (ns == null) ? node.getNodeName() : node.getLocalName();
310         for (Node JavaDoc n = this; n != null; n = n.getParentNode()) {
311             switch (n.getNodeType()) {
312             case ELEMENT_NODE:
313             case DOCUMENT_NODE:
314                 ElementsByTagName l = ad.getElementsByTagName(n, nm);
315                 if (l != null) {
316                     l.invalidate();
317                 }
318                 l = ad.getElementsByTagName(n, "*");
319                 if (l != null) {
320                     l.invalidate();
321                 }
322                 ElementsByTagNameNS lns = ad.getElementsByTagNameNS(n, ns, ln);
323
324                 if (lns != null) {
325                     lns.invalidate();
326                 }
327                 lns = ad.getElementsByTagNameNS(n, "*", ln);
328                 if (lns != null) {
329                     lns.invalidate();
330                 }
331                 lns = ad.getElementsByTagNameNS(n, ns, "*");
332                 if (lns != null) {
333                     lns.invalidate();
334                 }
335                 lns = ad.getElementsByTagNameNS(n, "*", "*");
336                 if (lns != null) {
337                     lns.invalidate();
338                 }
339             }
340         }
341
342         //
343
// Invalidate children
344
//
345
Node JavaDoc c = node.getFirstChild();
346         while (c != null) {
347             invalidateElementsByTagName(c);
348             c = c.getNextSibling();
349         }
350             
351     }
352
353     /**
354      * Creates the attribute list.
355      */

356     protected NamedNodeMap JavaDoc createAttributes() {
357     return new NamedNodeHashMap();
358     }
359
360     /**
361      * Exports this node to the given document.
362      * @param n The clone node.
363      * @param d The destination document.
364      */

365     protected Node JavaDoc export(Node JavaDoc n, AbstractDocument d) {
366     super.export(n, d);
367     AbstractElement ae = (AbstractElement)n;
368     if (attributes != null) {
369         NamedNodeMap JavaDoc map = attributes;
370         for (int i = map.getLength() - 1; i >= 0; i--) {
371         AbstractAttr aa = (AbstractAttr)map.item(i);
372         if (aa.getSpecified()) {
373             Attr JavaDoc attr = (Attr JavaDoc)aa.deepExport(aa.cloneNode(false), d);
374             if (aa instanceof AbstractAttrNS) {
375             ae.setAttributeNodeNS(attr);
376             } else {
377             ae.setAttributeNode(attr);
378             }
379         }
380         }
381     }
382     return n;
383     }
384
385     /**
386      * Deeply exports this node to the given document.
387      * @param n The clone node.
388      * @param d The destination document.
389      */

390     protected Node JavaDoc deepExport(Node JavaDoc n, AbstractDocument d) {
391     super.deepExport(n, d);
392     AbstractElement ae = (AbstractElement)n;
393     if (attributes != null) {
394         NamedNodeMap JavaDoc map = attributes;
395         for (int i = map.getLength() - 1; i >= 0; i--) {
396         AbstractAttr aa = (AbstractAttr)map.item(i);
397         if (aa.getSpecified()) {
398             Attr JavaDoc attr = (Attr JavaDoc)aa.deepExport(aa.cloneNode(false), d);
399             if (aa instanceof AbstractAttrNS) {
400             ae.setAttributeNodeNS(attr);
401             } else {
402             ae.setAttributeNode(attr);
403             }
404         }
405         }
406     }
407     return n;
408     }
409
410     /**
411      * Copy the fields of the current node into the given node.
412      * @param n a node of the type of this.
413      */

414     protected Node JavaDoc copyInto(Node JavaDoc n) {
415     super.copyInto(n);
416     AbstractElement ae = (AbstractElement)n;
417     if (attributes != null) {
418         NamedNodeMap JavaDoc map = attributes;
419         for (int i = map.getLength() - 1; i >= 0; i--) {
420         AbstractAttr aa = (AbstractAttr)map.item(i).cloneNode(true);
421         if (aa instanceof AbstractAttrNS) {
422             ae.setAttributeNodeNS(aa);
423         } else {
424             ae.setAttributeNode(aa);
425         }
426         }
427     }
428     return n;
429     }
430
431     /**
432      * Deeply copy the fields of the current node into the given node.
433      * @param n a node of the type of this.
434      */

435     protected Node JavaDoc deepCopyInto(Node JavaDoc n) {
436     super.deepCopyInto(n);
437     AbstractElement ae = (AbstractElement)n;
438     if (attributes != null) {
439         NamedNodeMap JavaDoc map = attributes;
440         for (int i = map.getLength() - 1; i >= 0; i--) {
441         AbstractAttr aa = (AbstractAttr)map.item(i).cloneNode(true);
442         if (aa instanceof AbstractAttrNS) {
443             ae.setAttributeNodeNS(aa);
444         } else {
445             ae.setAttributeNode(aa);
446         }
447         }
448     }
449     return n;
450     }
451
452     /**
453      * Checks the validity of a node to be inserted.
454      * @param n The node to be inserted.
455      */

456     protected void checkChildType(Node JavaDoc n, boolean replace) {
457     switch (n.getNodeType()) {
458     case ELEMENT_NODE:
459     case PROCESSING_INSTRUCTION_NODE:
460     case COMMENT_NODE:
461     case TEXT_NODE:
462     case CDATA_SECTION_NODE:
463     case ENTITY_REFERENCE_NODE:
464     case DOCUMENT_FRAGMENT_NODE:
465         break;
466     default:
467         throw createDOMException
468                 (DOMException.HIERARCHY_REQUEST_ERR,
469                  "child.type",
470                  new Object JavaDoc[] { new Integer JavaDoc(getNodeType()),
471                                 getNodeName(),
472                                 new Integer JavaDoc(n.getNodeType()),
473                                 n.getNodeName() });
474     }
475     }
476
477     /**
478      * Fires a DOMAttrModified event.
479      * WARNING: public accessor because of compilation problems
480      * on Solaris. Do not change.
481      *
482      * @param name The attribute's name.
483      * @param node The attribute's node.
484      * @param oldv The old value of the attribute.
485      * @param newv The new value of the attribute.
486      * @param change The modification type.
487      */

488     public void fireDOMAttrModifiedEvent(String JavaDoc name, Attr JavaDoc node, String JavaDoc oldv,
489                                          String JavaDoc newv, short change) {
490         switch (change) {
491         case MutationEvent.ADDITION:
492             if (((AbstractAttr)node).isId())
493                 ownerDocument.addIdEntry(this, newv);
494             attrAdded(node, newv);
495             break;
496
497         case MutationEvent.MODIFICATION:
498             if (((AbstractAttr)node).isId())
499                 ownerDocument.updateIdEntry(this, oldv, newv);
500             attrModified(node, oldv, newv);
501             break;
502
503         default: // MutationEvent.REMOVAL:
504
if (((AbstractAttr)node).isId())
505                 ownerDocument.removeIdEntry(this, oldv);
506             attrRemoved(node, oldv);
507         }
508     AbstractDocument doc = getCurrentDocument();
509     if (doc.getEventsEnabled() && !oldv.equals(newv)) {
510         DocumentEvent JavaDoc de = (DocumentEvent JavaDoc)doc;
511         MutationEvent JavaDoc ev = (MutationEvent JavaDoc)de.createEvent("MutationEvents");
512         ev.initMutationEvent("DOMAttrModified",
513                  true, // canBubbleArg
514
false, // cancelableArg
515
node, // relatedNodeArg
516
oldv, // prevValueArg
517
newv, // newValueArg
518
name, // attrNameArg
519
change); // attrChange
520
dispatchEvent(ev);
521     }
522     }
523
524     /**
525      * Called when an attribute has been added.
526      */

527     protected void attrAdded(Attr JavaDoc node, String JavaDoc newv) {
528     }
529
530     /**
531      * Called when an attribute has been modified.
532      */

533     protected void attrModified(Attr JavaDoc node, String JavaDoc oldv, String JavaDoc newv) {
534     }
535
536     /**
537      * Called when an attribute has been removed.
538      */

539     protected void attrRemoved(Attr JavaDoc node, String JavaDoc oldv) {
540     }
541
542     /**
543      * An implementation of the {@link org.w3c.dom.NamedNodeMap}.
544      */

545     public class NamedNodeHashMap implements NamedNodeMap JavaDoc, Serializable JavaDoc {
546
547         /**
548          * The initial capacity
549          */

550         protected final static int INITIAL_CAPACITY = 3;
551
552         /**
553          * The underlying array
554          */

555         protected Entry[] table;
556         
557         /**
558          * The number of entries
559          */

560         protected int count;
561         
562     /**
563      * Creates a new NamedNodeHashMap object.
564      */

565     public NamedNodeHashMap() {
566             table = new Entry[INITIAL_CAPACITY];
567     }
568
569     /**
570      * <b>DOM</b>: Implements {@link
571          * org.w3c.dom.NamedNodeMap#getNamedItem(String)}.
572      */

573     public Node JavaDoc getNamedItem(String JavaDoc name) {
574         if (name == null) {
575         return null;
576         }
577         return get(null, name);
578     }
579
580     /**
581      * <b>DOM</b>: Implements {@link
582          * org.w3c.dom.NamedNodeMap#setNamedItem(Node)}.
583      */

584     public Node JavaDoc setNamedItem(Node JavaDoc arg) throws DOMException JavaDoc {
585         if (arg == null) {
586         return null;
587         }
588         checkNode(arg);
589
590         return setNamedItem(null, arg.getNodeName(), arg);
591     }
592
593     /**
594      * <b>DOM</b>: Implements {@link
595      * org.w3c.dom.NamedNodeMap#removeNamedItem(String)}.
596      */

597     public Node JavaDoc removeNamedItem(String JavaDoc name) throws DOMException JavaDoc {
598         return removeNamedItemNS(null, name);
599     }
600
601     /**
602      * <b>DOM</b>: Implements {@link org.w3c.dom.NamedNodeMap#item(int)}.
603      */

604     public Node JavaDoc item(int index) {
605             if (index < 0 || index >= count) {
606                 return null;
607             }
608             int j = 0;
609             for (int i = 0; i < table.length; i++) {
610                 Entry e = table[i];
611                 if (e == null) {
612                     continue;
613                 }
614                 do {
615                     if (j++ == index) {
616                         return e.value;
617                     }
618                     e = e.next;
619                 } while (e != null);
620             }
621             return null;
622     }
623
624     /**
625      * <b>DOM</b>: Implements {@link org.w3c.dom.NamedNodeMap#getLength()}.
626      */

627     public int getLength() {
628             return count;
629     }
630
631     /**
632      * <b>DOM</b>: Implements {@link
633      * org.w3c.dom.NamedNodeMap#getNamedItemNS(String,String)}.
634      */

635     public Node JavaDoc getNamedItemNS(String JavaDoc namespaceURI, String JavaDoc localName) {
636             return get(namespaceURI, localName);
637     }
638
639     /**
640      * <b>DOM</b>: Implements {@link
641          * org.w3c.dom.NamedNodeMap#setNamedItemNS(Node)}.
642      */

643     public Node JavaDoc setNamedItemNS(Node JavaDoc arg) throws DOMException JavaDoc {
644         if (arg == null) {
645         return null;
646         }
647         String JavaDoc nsURI = arg.getNamespaceURI();
648             return setNamedItem(nsURI,
649                                 (nsURI == null)
650                                 ? arg.getNodeName()
651                                 : arg.getLocalName(), arg);
652     }
653
654     /**
655      * <b>DOM</b>: Implements {@link
656      * org.w3c.dom.NamedNodeMap#removeNamedItemNS(String,String)}.
657      */

658     public Node JavaDoc removeNamedItemNS(String JavaDoc namespaceURI, String JavaDoc localName)
659         throws DOMException JavaDoc {
660         if (isReadonly()) {
661         throw createDOMException
662                     (DOMException.NO_MODIFICATION_ALLOWED_ERR,
663                      "readonly.node.map",
664                      new Object JavaDoc[] {});
665         }
666         if (localName == null) {
667         throw createDOMException(DOMException.NOT_FOUND_ERR,
668                      "attribute.missing",
669                      new Object JavaDoc[] { "" });
670         }
671         AbstractAttr n = (AbstractAttr)remove(namespaceURI, localName);
672         if (n == null) {
673         throw createDOMException(DOMException.NOT_FOUND_ERR,
674                      "attribute.missing",
675                      new Object JavaDoc[] { localName });
676         }
677         n.setOwnerElement(null);
678         
679         // Mutation event
680
fireDOMAttrModifiedEvent(n.getNodeName(), n, n.getNodeValue(), "",
681                                      MutationEvent.REMOVAL);
682         return n;
683     }
684
685     /**
686      * Adds a node to the map.
687      */

688     public Node JavaDoc setNamedItem(String JavaDoc ns, String JavaDoc name, Node JavaDoc arg)
689             throws DOMException JavaDoc {
690         ((AbstractAttr)arg).setOwnerElement(AbstractElement.this);
691         AbstractAttr result = (AbstractAttr)put(ns, name, arg);
692
693         if (result != null) {
694         result.setOwnerElement(null);
695         fireDOMAttrModifiedEvent(name,
696                                          result,
697                      result.getNodeValue(),
698                      "",
699                                          MutationEvent.REMOVAL);
700         }
701             fireDOMAttrModifiedEvent(name,
702                                      (Attr JavaDoc)arg,
703                                      "",
704                                      arg.getNodeValue(),
705                                      MutationEvent.ADDITION);
706         return result;
707     }
708
709     /**
710      * Checks the validity of a node to add.
711      */

712     protected void checkNode(Node JavaDoc arg) {
713         if (isReadonly()) {
714         throw createDOMException
715                     (DOMException.NO_MODIFICATION_ALLOWED_ERR,
716                      "readonly.node.map",
717                      new Object JavaDoc[] {});
718         }
719         if (getOwnerDocument() != arg.getOwnerDocument()) {
720         throw createDOMException(DOMException.WRONG_DOCUMENT_ERR,
721                      "node.from.wrong.document",
722                      new Object JavaDoc[] { new Integer JavaDoc
723                                                          (arg.getNodeType()),
724                                                 arg.getNodeName() });
725         }
726         if (arg.getNodeType() == ATTRIBUTE_NODE &&
727         ((Attr JavaDoc)arg).getOwnerElement() != null) {
728         throw createDOMException(DOMException.WRONG_DOCUMENT_ERR,
729                      "inuse.attribute",
730                      new Object JavaDoc[] { arg.getNodeName() });
731         }
732     }
733
734         /**
735          * Gets the value of a variable
736          * @return the value or null
737          */

738         protected Node JavaDoc get(String JavaDoc ns, String JavaDoc nm) {
739             int hash = hashCode(ns, nm) & 0x7FFFFFFF;
740             int index = hash % table.length;
741     
742             for (Entry e = table[index]; e != null; e = e.next) {
743                 if ((e.hash == hash) && e.match(ns, nm)) {
744                     return e.value;
745                 }
746             }
747             return null;
748         }
749     
750         /**
751          * Sets a new value for the given variable
752          * @return the old value or null
753          */

754         protected Node JavaDoc put(String JavaDoc ns, String JavaDoc nm, Node JavaDoc value) {
755             int hash = hashCode(ns, nm) & 0x7FFFFFFF;
756             int index = hash % table.length;
757     
758             for (Entry e = table[index]; e != null; e = e.next) {
759                 if ((e.hash == hash) && e.match(ns, nm)) {
760                     Node JavaDoc old = e.value;
761                     e.value = value;
762                     return old;
763                 }
764             }
765     
766             // The key is not in the hash table
767
int len = table.length;
768             if (count++ >= (len * 3) >>> 2) {
769                 rehash();
770                 index = hash % table.length;
771             }
772             
773             Entry e = new Entry(hash, ns, nm, value, table[index]);
774             table[index] = e;
775             return null;
776         }
777
778         /**
779          * Removes an entry from the table.
780          * @return the value or null.
781          */

782         protected Node JavaDoc remove(String JavaDoc ns, String JavaDoc nm) {
783             int hash = hashCode(ns, nm) & 0x7FFFFFFF;
784             int index = hash % table.length;
785     
786             Entry p = null;
787             for (Entry e = table[index]; e != null; e = e.next) {
788                 if ((e.hash == hash) && e.match(ns, nm)) {
789                     Node JavaDoc result = e.value;
790                     if (p == null) {
791                         table[index] = e.next;
792                     } else {
793                         p.next = e.next;
794                     }
795                     count--;
796                     return result;
797                 }
798                 p = e;
799             }
800             return null;
801         }
802
803         /**
804          * Rehash the table
805          */

806         protected void rehash () {
807             Entry[] oldTable = table;
808     
809             table = new Entry[oldTable.length * 2 + 1];
810     
811             for (int i = oldTable.length-1; i >= 0; i--) {
812                 for (Entry old = oldTable[i]; old != null;) {
813                     Entry e = old;
814                     old = old.next;
815                     
816                     int index = e.hash % table.length;
817                     e.next = table[index];
818                     table[index] = e;
819                 }
820             }
821         }
822
823         /**
824          * Computes a hash code corresponding to the given strings.
825          */

826         protected int hashCode(String JavaDoc ns, String JavaDoc nm) {
827             int result = (ns == null) ? 0 : ns.hashCode();
828             return result ^ nm.hashCode();
829         }
830     }
831
832     /**
833      * To manage collisions in the attributes map.
834      */

835     protected static class Entry implements Serializable JavaDoc {
836
837         /**
838          * The hash code
839          */

840         public int hash;
841     
842         /**
843          * The namespace URI
844          */

845         public String JavaDoc namespaceURI;
846     
847         /**
848          * The node name.
849          */

850         public String JavaDoc name;
851         
852         /**
853          * The value
854          */

855         public Node JavaDoc value;
856     
857         /**
858          * The next entry
859          */

860         public Entry next;
861     
862         /**
863          * Creates a new entry
864          */

865         public Entry(int hash, String JavaDoc ns, String JavaDoc nm, Node JavaDoc value, Entry next) {
866             this.hash = hash;
867             this.namespaceURI = ns;
868             this.name = nm;
869             this.value = value;
870             this.next = next;
871         }
872         
873         /**
874          * Whether this entry match the given keys.
875          */

876         public boolean match(String JavaDoc ns, String JavaDoc nm) {
877             if (namespaceURI != null) {
878                 if (!namespaceURI.equals(ns)) {
879                     return false;
880                 }
881             } else if (ns != null) {
882                 return false;
883             }
884             return name.equals(nm);
885         }
886     }
887
888 }
889
Popular Tags