KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > dom > AttributeMap


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.dom;
59
60 import java.util.Vector JavaDoc;
61
62 import org.w3c.dom.DOMException JavaDoc;
63 import org.w3c.dom.Node JavaDoc;
64
65
66 /**
67  * AttributeMap inherits from NamedNodeMapImpl and extends it to deal with the
68  * specifics of storing attributes. These are:
69  * <ul>
70  * <li>managing ownership of attribute nodes
71  * <li>managing default attributes
72  * <li>firing mutation events
73  * </ul>
74  * <p>
75  * This class doesn't directly support mutation events, however, it notifies
76  * the document when mutations are performed so that the document class do so.
77  *
78  */

79 public class AttributeMap extends NamedNodeMapImpl {
80
81     //
82
// Constructors
83
//
84

85     /** Constructs a named node map. */
86     protected AttributeMap(ElementImpl ownerNode, NamedNodeMapImpl defaults) {
87         super(ownerNode);
88         if (defaults != null) {
89             // initialize map with the defaults
90
cloneContent(defaults);
91             if (nodes != null) {
92                 hasDefaults(true);
93             }
94         }
95     }
96
97     /**
98      * Adds an attribute using its nodeName attribute.
99      * @see org.w3c.dom.NamedNodeMap#setNamedItem
100      * @return If the new Node replaces an existing node the replaced Node is
101      * returned, otherwise null is returned.
102      * @param arg
103      * An Attr node to store in this map.
104      * @exception org.w3c.dom.DOMException The exception description.
105      */

106     public Node JavaDoc setNamedItem(Node JavaDoc arg)
107         throws DOMException JavaDoc {
108
109         if (isReadOnly()) {
110             throw
111                 new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR,
112                                      "DOM001 Modification not allowed");
113         }
114         if(arg.getOwnerDocument() != ownerNode.ownerDocument()) {
115             throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR,
116                                        "DOM005 Wrong document");
117         }
118         if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
119             throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
120                                    "DOM006 Hierarchy request error");
121         }
122
123         AttrImpl argn = (AttrImpl)arg;
124
125         if (argn.isOwned()) {
126             throw new DOMException JavaDoc(DOMException.INUSE_ATTRIBUTE_ERR,
127                                        "DOM009 Attribute already in use");
128         }
129
130         // set owner
131
argn.ownerNode = ownerNode;
132         argn.isOwned(true);
133
134     int i = findNamePoint(arg.getNodeName(),0);
135         AttrImpl previous = null;
136         if (i >= 0) {
137             previous = (AttrImpl) nodes.elementAt(i);
138             nodes.setElementAt(arg,i);
139             previous.ownerNode = ownerNode.ownerDocument();
140             previous.isOwned(false);
141             // make sure it won't be mistaken with defaults in case it's reused
142
previous.isSpecified(true);
143         } else {
144             i = -1 - i; // Insert point (may be end of list)
145
if (null == nodes) {
146                 nodes = new Vector JavaDoc(5, 10);
147             }
148             nodes.insertElementAt(arg, i);
149         }
150
151         // notify document
152
ownerNode.ownerDocument().setAttrNode(argn, previous);
153
154         // If the new attribute is not normalized,
155
// the owning element is inherently not normalized.
156
if (!argn.isNormalized()) {
157             ownerNode.isNormalized(false);
158         }
159         return previous;
160
161     } // setNamedItem(Node):Node
162

163     /**
164      * Adds an attribute using its namespaceURI and localName.
165      * @see org.w3c.dom.NamedNodeMap#setNamedItem
166      * @return If the new Node replaces an existing node the replaced Node is
167      * returned, otherwise null is returned.
168      * @param arg A node to store in a named node map.
169      */

170     public Node JavaDoc setNamedItemNS(Node JavaDoc arg)
171         throws DOMException JavaDoc {
172
173         if (isReadOnly()) {
174             throw
175                 new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR,
176                                      "DOM001 Modification not allowed");
177         }
178     
179         if(arg.getOwnerDocument() != ownerNode.ownerDocument()) {
180             throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR,
181                                        "DOM005 Wrong document");
182         }
183
184         if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
185             throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
186                                    "DOM006 Hierarchy request error");
187         }
188         AttrImpl argn = (AttrImpl)arg;
189         if (argn.isOwned()) {
190             throw new DOMException JavaDoc(DOMException.INUSE_ATTRIBUTE_ERR,
191                                        "DOM009 Attribute already in use");
192         }
193
194         // set owner
195
argn.ownerNode = ownerNode;
196         argn.isOwned(true);
197
198         int i = findNamePoint(argn.getNamespaceURI(), argn.getLocalName());
199         AttrImpl previous = null;
200         if (i >= 0) {
201             previous = (AttrImpl) nodes.elementAt(i);
202             nodes.setElementAt(arg,i);
203             previous.ownerNode = ownerNode.ownerDocument();
204             previous.isOwned(false);
205             // make sure it won't be mistaken with defaults in case it's reused
206
previous.isSpecified(true);
207         } else {
208             // If we can't find by namespaceURI, localName, then we find by
209
// nodeName so we know where to insert.
210
i = findNamePoint(arg.getNodeName(),0);
211             if (i >=0) {
212                 previous = (AttrImpl) nodes.elementAt(i);
213                 nodes.insertElementAt(arg,i);
214             } else {
215                 i = -1 - i; // Insert point (may be end of list)
216
if (null == nodes) {
217                     nodes = new Vector JavaDoc(5, 10);
218                 }
219                 nodes.insertElementAt(arg, i);
220             }
221         }
222         // changed(true);
223

224         // notify document
225
ownerNode.ownerDocument().setAttrNode(argn, previous);
226
227         // If the new attribute is not normalized,
228
// the owning element is inherently not normalized.
229
if (!argn.isNormalized()) {
230             ownerNode.isNormalized(false);
231         }
232         return previous;
233
234     } // setNamedItemNS(Node):Node
235

236     /**
237      * Removes an attribute specified by name.
238      * @param name
239      * The name of a node to remove. If the
240      * removed attribute is known to have a default value, an
241      * attribute immediately appears containing the default value
242      * as well as the corresponding namespace URI, local name,
243      * and prefix when applicable.
244      * @return The node removed from the map if a node with such a name exists.
245      * @throws NOT_FOUND_ERR: Raised if there is no node named
246      * name in the map.
247      */

248     /***/
249     public Node JavaDoc removeNamedItem(String JavaDoc name)
250         throws DOMException JavaDoc {
251         return internalRemoveNamedItem(name, true);
252     }
253
254     /**
255      * Same as removeNamedItem except that it simply returns null if the
256      * specified name is not found.
257      */

258     Node JavaDoc safeRemoveNamedItem(String JavaDoc name) {
259         return internalRemoveNamedItem(name, false);
260     }
261
262     /**
263      * Internal removeNamedItem method allowing to specify whether an exception
264      * must be thrown if the specified name is not found.
265      */

266     final protected Node JavaDoc internalRemoveNamedItem(String JavaDoc name, boolean raiseEx){
267         if (isReadOnly()) {
268             throw
269                 new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR,
270                                      "DOM001 Modification not allowed");
271         }
272         int i = findNamePoint(name,0);
273         if (i < 0) {
274             if (raiseEx) {
275                 throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR,
276                                            "DOM008 Not found");
277             } else {
278                 return null;
279             }
280         }
281
282         AttrImpl n = (AttrImpl)nodes.elementAt(i);
283         CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
284
285         // If there's a default, add it instead
286
if (hasDefaults()) {
287             NamedNodeMapImpl defaults =
288                 ((ElementImpl) ownerNode).getDefaultAttributes();
289             Node JavaDoc d;
290             if (defaults != null && (d = defaults.getNamedItem(name)) != null
291                 && findNamePoint(name, i+1) < 0) {
292
293                 NodeImpl clone = (NodeImpl)d.cloneNode(true);
294                 clone.ownerNode = ownerNode;
295                 clone.isOwned(true);
296                 clone.isSpecified(false);
297                 nodes.setElementAt(clone, i);
298             } else {
299                 nodes.removeElementAt(i);
300             }
301         } else {
302             nodes.removeElementAt(i);
303         }
304
305         // changed(true);
306

307         // remove reference to owner
308
n.ownerNode = ownerDocument;
309         n.isOwned(false);
310         // make sure it won't be mistaken with defaults in case it's reused
311
n.isSpecified(true);
312
313         // notify document
314
ownerDocument.removedAttrNode(n, ownerNode, name);
315
316         return n;
317
318     } // internalRemoveNamedItem(String,boolean):Node
319

320     /**
321      * Introduced in DOM Level 2. <p>
322      * Removes an attribute specified by local name and namespace URI.
323      * @param namespaceURI
324      * The namespace URI of the node to remove.
325      * When it is null or an empty string, this
326      * method behaves like removeNamedItem.
327      * @param The local name of the node to remove. If the
328      * removed attribute is known to have a default
329      * value, an attribute immediately appears
330      * containing the default value.
331      * @return Node The node removed from the map if a node with such
332      * a local name and namespace URI exists.
333      * @throws NOT_FOUND_ERR: Raised if there is no node named
334      * name in the map.
335      */

336     public Node JavaDoc removeNamedItemNS(String JavaDoc namespaceURI, String JavaDoc name)
337         throws DOMException JavaDoc {
338         return internalRemoveNamedItemNS(namespaceURI, name, true);
339     }
340
341     /**
342      * Same as removeNamedItem except that it simply returns null if the
343      * specified local name and namespace URI is not found.
344      */

345     Node JavaDoc safeRemoveNamedItemNS(String JavaDoc namespaceURI, String JavaDoc name) {
346         return internalRemoveNamedItemNS(namespaceURI, name, false);
347     }
348
349     /**
350      * Internal removeNamedItemNS method allowing to specify whether an
351      * exception must be thrown if the specified local name and namespace URI
352      * is not found.
353      */

354     final protected Node JavaDoc internalRemoveNamedItemNS(String JavaDoc namespaceURI,
355                                                    String JavaDoc name,
356                                                    boolean raiseEx) {
357         if (isReadOnly()) {
358             throw
359                 new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR,
360                                      "DOM001 Modification not allowed");
361         }
362         int i = findNamePoint(namespaceURI, name);
363         if (i < 0) {
364             if (raiseEx) {
365                 throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR,
366                                            "DOM008 Not found");
367             } else {
368                 return null;
369             }
370         }
371
372         AttrImpl n = (AttrImpl)nodes.elementAt(i);
373         CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
374
375         // If there's a default, add it instead
376
String JavaDoc nodeName = n.getNodeName();
377         if (hasDefaults()) {
378             NamedNodeMapImpl defaults =
379                 ((ElementImpl) ownerNode).getDefaultAttributes();
380             Node JavaDoc d;
381             if (defaults != null
382                 && (d = defaults.getNamedItem(nodeName)) != null)
383                 {
384                     int j = findNamePoint(nodeName,0);
385                     if (j>=0 && findNamePoint(nodeName, j+1) < 0) {
386                         NodeImpl clone = (NodeImpl)d.cloneNode(true);
387                         clone.ownerNode = ownerNode;
388                          // we must rely on the name to find a default attribute
389
// ("test:attr"), but while copying it from the DOCTYPE
390
// we should not loose namespace URI that was assigned
391
// to the attribute in the instance document.
392
if (clone instanceof AttrNSImpl) {
393                             ((AttrNSImpl)clone).namespaceURI = namespaceURI;
394                         }
395                         clone.isOwned(true);
396                         clone.isSpecified(false);
397                         nodes.setElementAt(clone, i);
398                     } else {
399                         nodes.removeElementAt(i);
400                     }
401                 } else {
402                     nodes.removeElementAt(i);
403                 }
404         } else {
405             nodes.removeElementAt(i);
406         }
407
408         // changed(true);
409

410         // remove reference to owner
411
n.ownerNode = ownerDocument;
412         n.isOwned(false);
413         // make sure it won't be mistaken with defaults in case it's reused
414
n.isSpecified(true);
415
416         // notify document
417
ownerDocument.removedAttrNode(n, ownerNode, name);
418
419         return n;
420
421     } // internalRemoveNamedItemNS(String,String,boolean):Node
422

423     //
424
// Public methods
425
//
426

427     /**
428      * Cloning a NamedNodeMap is a DEEP OPERATION; it always clones
429      * all the nodes contained in the map.
430      */

431      
432     public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
433         AttributeMap newmap =
434             new AttributeMap((ElementImpl) ownerNode, null);
435         newmap.hasDefaults(hasDefaults());
436         newmap.cloneContent(this);
437         return newmap;
438     } // cloneMap():AttributeMap
439

440     /**
441      * Override parent's method to set the ownerNode correctly
442      */

443     protected void cloneContent(NamedNodeMapImpl srcmap) {
444         if (srcmap.nodes != null) {
445             if (nodes == null) {
446                 nodes = new Vector JavaDoc(srcmap.nodes.size());
447             }
448             else {
449                 nodes.setSize(srcmap.nodes.size());
450             }
451             for (int i = 0; i < srcmap.nodes.size(); ++i) {
452                 NodeImpl n = (NodeImpl) srcmap.nodes.elementAt(i);
453                 NodeImpl clone = (NodeImpl) n.cloneNode(true);
454                 clone.isSpecified(n.isSpecified());
455                 nodes.insertElementAt(clone, i);
456                 clone.ownerNode = ownerNode;
457                 clone.isOwned(true);
458             }
459         }
460     } // cloneContent():AttributeMap
461

462
463     /**
464      * Get this AttributeMap in sync with the given "defaults" map.
465      * @param defaults The default attributes map to sync with.
466      */

467     protected void reconcileDefaults(NamedNodeMapImpl defaults) {
468         
469         // remove any existing default
470
int nsize = (nodes != null) ? nodes.size() : 0;
471         for (int i = nsize - 1; i >= 0; i--) {
472             AttrImpl attr = (AttrImpl) nodes.elementAt(i);
473             if (!attr.isSpecified()) {
474                 // remove owning element
475
attr.ownerNode = ownerNode.ownerDocument();
476                 attr.isOwned(false);
477                 // make sure it won't be mistaken in case it's reused
478
attr.isSpecified(true);
479                 nodes.removeElementAt(i);
480             }
481         }
482         // add the new defaults
483
if (defaults == null) {
484             return;
485         }
486         if (nodes == null || nodes.size() == 0) {
487             cloneContent(defaults);
488         }
489         else {
490             int dsize = defaults.nodes.size();
491             for (int n = 0; n < dsize; n++) {
492                 AttrImpl d = (AttrImpl) defaults.nodes.elementAt(n);
493                 int i = findNamePoint(d.getNodeName(), 0);
494                 if (i < 0) {
495                     NodeImpl clone = (NodeImpl) d.cloneNode(true);
496                     clone.ownerNode = ownerNode;
497                     clone.isOwned(true);
498                     clone.isSpecified(false);
499                     nodes.setElementAt(clone, i);
500                 }
501             }
502         }
503
504     } // reconcileDefaults()
505

506 } // class AttributeMap
507
Popular Tags