Merge from mainline
[official-gcc.git] / libjava / classpath / gnu / xml / dom / DomNamedNodeMap.java
blobe3f08e4b4b78f1a1045182014f6716c84ddcd9ee
1 /* DomNamedNodeMap.java --
2 Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.xml.dom;
40 import org.w3c.dom.DOMException;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.Node;
44 /**
45 * <p> "NamedNodeMap" implementation. </p>
46 * Used mostly to hold element attributes, but sometimes also
47 * to list notations or entities.
49 * @author David Brownell
50 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
52 public class DomNamedNodeMap
53 implements NamedNodeMap
56 final DomNode owner;
57 final short type;
59 DomNode first;
60 int length;
61 boolean readonly;
63 // package private
64 DomNamedNodeMap(DomNode owner, short type)
66 this.owner = owner;
67 this.type = type;
70 /**
71 * Exposes the internal "readonly" flag. In DOM, all NamedNodeMap
72 * objects found in a DocumentType object are read-only (after
73 * they are fully constructed), and those holding attributes of
74 * a readonly element will also be readonly.
76 public final boolean isReadonly()
78 return readonly;
81 /**
82 * Sets the internal "readonly" flag so the node and its
83 * children can't be changed.
85 public void makeReadonly()
87 readonly = true;
88 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
90 ctx.makeReadonly();
94 /**
95 * <b>DOM L1</b>
96 * Returns the named item from the map, or null; names are just
97 * the nodeName property.
99 public Node getNamedItem(String name)
101 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
103 if (ctx.getNodeName().equals(name))
105 return ctx;
108 return null;
112 * <b>DOM L2</b>
113 * Returns the named item from the map, or null; names are the
114 * localName and namespaceURI properties, ignoring any prefix.
116 public Node getNamedItemNS(String namespaceURI, String localName)
118 if ("".equals(namespaceURI))
120 namespaceURI = null;
122 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
124 String name = ctx.getLocalName();
125 if ((localName == null && name == null) ||
126 (localName != null && localName.equals(name)))
128 String uri = ctx.getNamespaceURI();
129 if ("".equals(uri))
131 uri = null;
133 if ((namespaceURI == null && uri == null) ||
134 (namespaceURI != null && namespaceURI.equals(uri)))
136 return ctx;
140 return null;
144 * <b>DOM L1</b>
145 * Stores the named item into the map, optionally overwriting
146 * any existing node with that name. The name used is just
147 * the nodeName attribute.
149 public Node setNamedItem(Node arg)
151 return setNamedItem(arg, false);
155 * <b>DOM L2</b>
156 * Stores the named item into the map, optionally overwriting
157 * any existing node with that fully qualified name. The name
158 * used incorporates the localName and namespaceURI properties,
159 * and ignores any prefix.
161 public Node setNamedItemNS(Node arg)
163 return setNamedItem(arg, true);
166 Node setNamedItem(Node arg, boolean ns)
168 if (readonly)
170 throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
173 DomNode node = (DomNode) arg;
174 if (node.owner != owner.owner)
176 throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR);
178 if (node.nodeType != type)
180 throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR);
182 if (node.nodeType == Node.ATTRIBUTE_NODE)
184 DomNode element = node.parent;
185 if (element != null && element != owner)
187 throw new DomDOMException(DOMException.INUSE_ATTRIBUTE_ERR);
189 node.parent = owner;
190 node.depth = owner.depth + 1;
193 String nodeName = node.getNodeName();
194 String localName = ns ? node.getLocalName() : null;
195 String namespaceURI = ns ? node.getNamespaceURI() : null;
196 if ("".equals(namespaceURI))
198 namespaceURI = null;
201 // maybe attribute ADDITION events (?)
202 DomNode last = null;
203 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
205 boolean test = false;
206 if (ns)
208 String tln = ctx.getLocalName();
209 if (tln == null)
211 tln = ctx.getNodeName();
213 if (tln.equals(localName))
215 String tu = ctx.getNamespaceURI();
216 if ((tu == null && namespaceURI == null) ||
217 (tu != null && tu.equals(namespaceURI)))
219 test = true;
223 else
225 test = ctx.getNodeName().equals(nodeName);
227 if (test)
229 // replace
230 node.previous = ctx.previous;
231 node.next = ctx.next;
232 if (ctx.previous != null)
234 ctx.previous.next = node;
236 if (ctx.next != null)
238 ctx.next.previous = node;
240 if (first == ctx)
242 first = node;
244 reparent(node, nodeName, ctx.index);
245 ctx.parent = null;
246 ctx.next = null;
247 ctx.previous = null;
248 ctx.setDepth(0);
249 ctx.index = 0;
250 return ctx;
252 last = ctx;
254 // append
255 if (last != null)
257 last.next = node;
258 node.previous = last;
260 else
262 first = node;
264 length++;
265 reparent(node, nodeName, 0);
266 return null;
269 void reparent(DomNode node, String nodeName, int i)
271 node.parent = owner;
272 node.setDepth(owner.depth + 1);
273 // index renumbering
274 for (DomNode ctx = node; ctx != null; ctx = ctx.next)
276 ctx.index = i++;
278 // cache xml:space
279 boolean xmlSpace = "xml:space".equals(nodeName);
280 if (xmlSpace && owner instanceof DomElement)
282 ((DomElement) owner).xmlSpace = node.getNodeValue();
287 * <b>DOM L1</b>
288 * Removes the named item from the map, or reports an exception;
289 * names are just the nodeName property.
291 public Node removeNamedItem(String name)
293 return removeNamedItem(null, name, false);
297 * <b>DOM L2</b>
298 * Removes the named item from the map, or reports an exception;
299 * names are the localName and namespaceURI properties.
301 public Node removeNamedItemNS(String namespaceURI, String localName)
303 return removeNamedItem(namespaceURI, localName, true);
306 Node removeNamedItem(String uri, String name, boolean ns)
308 if (readonly)
310 throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
313 // report attribute REMOVAL event?
315 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
317 boolean test = false;
318 String nodeName = ctx.getNodeName();
319 if (ns)
321 String tln = ctx.getLocalName();
322 if (name != null && name.equals(tln))
324 String tu = ctx.getNamespaceURI();
325 if ((tu == null && uri == null) ||
326 (tu != null && tu.equals(uri)))
328 test = true;
332 else
334 test = nodeName.equals(name);
336 if (test)
338 // uncache xml:space
339 boolean xmlSpace = "xml:space".equals(nodeName);
340 if (xmlSpace && owner instanceof DomElement)
342 ((DomElement) owner).xmlSpace = "";
344 // is this a default attribute?
345 if (ctx.nodeType == Node.ATTRIBUTE_NODE)
347 String def = getDefaultValue(ctx.getNodeName());
348 if (def != null)
350 ctx.setNodeValue(def);
351 ((DomAttr) ctx).setSpecified(false);
352 return null;
355 // remove
356 if (ctx == first)
358 first = ctx.next;
360 if (ctx.previous != null)
362 ctx.previous.next = ctx.next;
364 if (ctx.next != null)
366 ctx.next.previous = ctx.previous;
368 length--;
369 ctx.previous = null;
370 ctx.next = null;
371 ctx.parent = null;
372 ctx.setDepth(0);
373 ctx.index = 0;
374 return ctx;
377 throw new DomDOMException(DOMException.NOT_FOUND_ERR);
380 String getDefaultValue(String name)
382 DomDoctype doctype = (DomDoctype) owner.owner.getDoctype();
383 if (doctype == null)
385 return null;
387 DTDAttributeTypeInfo info =
388 doctype.getAttributeTypeInfo(owner.getNodeName(), name);
389 if (info == null)
391 return null;
393 return info.value;
397 * <b>DOM L1</b>
398 * Returns the indexed item from the map, or null.
400 public Node item(int index)
402 DomNode ctx = first;
403 int count = 0;
404 while (ctx != null && count < index)
406 ctx = ctx.next;
407 count++;
409 return ctx;
413 * <b>DOM L1</b>
414 * Returns the length of the map.
416 public int getLength()
418 return length;