Merge from the pain train
[official-gcc.git] / libjava / gnu / xml / dom / DomAttr.java
blob555902e3ea3597d5e84c0978efcaa324d82553c2
1 /* DomAttr.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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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.Attr;
41 import org.w3c.dom.DOMException;
42 import org.w3c.dom.Element;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.TypeInfo;
45 import org.w3c.dom.events.MutationEvent;
48 /**
49 * <p> "Attr" implementation. In DOM, attributes cost quite a lot of
50 * memory because their values are complex structures rather than just
51 * simple strings. To reduce your costs, avoid having more than one
52 * child of an attribute; stick to a single Text node child, and ignore
53 * even that by using the attribute's "nodeValue" property.</p>
55 * <p> As a bit of general advice, only look at attribute modification
56 * events through the DOMAttrModified event (sent to the associated
57 * element). Implementations are not guaranteed to report other events
58 * in the same order, so you're very likely to write nonportable code if
59 * you monitor events at the "children of Attr" level.</p>
61 * <p> At this writing, not all attribute modifications will cause the
62 * DOMAttrModified event to be triggered ... only the ones using the string
63 * methods (setNodeValue, setValue, and Element.setAttribute) to modify
64 * those values. That is, if you manipulate those children directly,
65 * elements won't get notified that attribute values have changed.
66 * The natural fix for that will report other modifications, but won't
67 * be able to expose "previous" attribute value; it'll need to be cached
68 * or something (at which point why bother using child nodes). </p>
70 * <p><em>You are strongly advised not to use "children" of any attribute
71 * nodes you work with.</em> </p>
73 * @author David Brownell
74 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
76 public class DomAttr
77 extends DomNsNode
78 implements Attr
81 private boolean specified;
82 private String value; // string value cache
84 /**
85 * Constructs an Attr node associated with the specified document.
86 * The "specified" flag is initialized to true, since this DOM has
87 * no current "back door" mechanisms to manage default values so
88 * that every value must effectively be "specified".
90 * <p>This constructor should only be invoked by a Document as part of
91 * its createAttribute functionality, or through a subclass which is
92 * similarly used in a "Sub-DOM" style layer.
94 * @param owner The document with which this node is associated
95 * @param namespaceURI Combined with the local part of the name,
96 * this is used to uniquely identify a type of attribute
97 * @param name Name of this attribute, which may include a prefix
99 protected DomAttr(DomDocument owner, String namespaceURI, String name)
101 super(ATTRIBUTE_NODE, owner, namespaceURI, name);
102 specified = true;
103 length = 1;
105 // XXX register self to get insertion/removal events
106 // and character data change events and when they happen,
107 // report self-mutation
111 * <b>DOM L1</b>
112 * Returns the attribute name (same as getNodeName)
114 public final String getName()
116 return getNodeName();
120 * <b>DOM L1</b>
121 * Returns true if a parser reported this was in the source text.
123 public final boolean getSpecified()
125 return specified;
129 * Records whether this attribute was in the source text.
131 public final void setSpecified(boolean value)
133 specified = value;
137 * <b>DOM L1</b>
138 * Returns the attribute value, with character and entity
139 * references substituted.
140 * <em>NOTE: entity refs as children aren't currently handled.</em>
142 public String getNodeValue()
144 // If we have a simple node-value, use that
145 if (first == null)
147 return (value == null) ? "" : value;
149 // Otherwise collect child node-values
150 StringBuffer buf = new StringBuffer();
151 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
153 switch (ctx.nodeType)
155 case Node.TEXT_NODE:
156 buf.append(ctx.getNodeValue());
157 break;
158 case Node.ENTITY_REFERENCE_NODE:
159 // TODO
160 break;
163 return buf.toString();
167 * <b>DOM L1</b>
168 * Assigns the value of the attribute; it will have one child,
169 * which is a text node with the specified value (same as
170 * setNodeValue).
172 public final void setValue(String value)
174 setNodeValue(value);
178 * <b>DOM L1</b>
179 * Returns the value of the attribute as a non-null string; same
180 * as getNodeValue.
181 * <em>NOTE: entity refs as children aren't currently handled.</em>
183 public final String getValue()
185 return getNodeValue();
189 * <b>DOM L1</b>
190 * Assigns the attribute value; using this API, no entity or
191 * character references will exist.
192 * Causes a DOMAttrModified mutation event to be sent.
194 public void setNodeValue(String value)
196 if (readonly)
198 throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
200 if (value == null)
202 value = "";
204 String oldValue = getNodeValue();
205 while (last != null)
207 removeChild(last);
209 // don't create a new node just for this...
211 Node text = owner.createTextNode(value);
212 appendChild(text);
214 this.value = value;
215 length = 1;
216 specified = true;
218 mutating(oldValue, value, MutationEvent.MODIFICATION);
221 public final Node getFirstChild()
223 // Create a child text node if necessary
224 if (first == null)
226 length = 0;
227 Node text = owner.createTextNode((value == null) ? "" : value);
228 appendChild(text);
230 return first;
233 public final Node getLastChild()
235 // Create a child text node if necessary
236 if (last == null)
238 length = 0;
239 Node text = owner.createTextNode((value == null) ? "" : value);
240 appendChild(text);
242 return last;
245 public Node item(int index)
247 // Create a child text node if necessary
248 if (first == null)
250 length = 0;
251 Node text = owner.createTextNode((value == null) ? "" : value);
252 appendChild(text);
254 return super.item(index);
258 * <b>DOM L2</b>
259 * Returns the element with which this attribute is associated.
261 public final Element getOwnerElement()
263 return (Element) parent;
266 public final Node getNextSibling()
268 return null;
271 public final Node getPreviousSibling()
273 return null;
276 public Node getParentNode()
278 return null;
282 * Records the element with which this attribute is associated.
284 public final void setOwnerElement(Element e)
286 if (parent != null)
288 throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR);
290 if (!(e instanceof DomElement))
292 throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR);
294 parent = (DomElement) e;
295 depth = parent.depth + 1;
299 * The base URI of an Attr is always <code>null</code>.
301 public final String getBaseURI()
303 return null;
307 * Shallow clone of the attribute, breaking all ties with any
308 * elements.
310 public Object clone()
312 DomAttr retval = (DomAttr) super.clone();
313 retval.specified = true;
314 return retval;
317 private void mutating(String oldValue, String newValue, short why)
319 if (!reportMutations || parent == null)
321 return;
324 // EVENT: DOMAttrModified, target = parent,
325 // prev/new values provided, also attr name
326 MutationEvent event;
328 event = (MutationEvent) createEvent ("MutationEvents");
329 event.initMutationEvent ("DOMAttrModified",
330 true /* bubbles */, false /* nocancel */,
331 null, oldValue, newValue, getNodeName (), why);
332 parent.dispatchEvent (event);
335 // DOM Level 3 methods
337 public TypeInfo getSchemaTypeInfo()
339 if (parent != null)
341 // DTD implementation
342 DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
343 if (doctype != null)
345 return doctype.getAttributeTypeInfo(parent.getNodeName(),
346 getNodeName());
348 // TODO XML Schema implementation
350 return null;
353 public boolean isId()
355 if (parent != null)
357 DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
358 if (doctype != null)
360 DTDAttributeTypeInfo info =
361 doctype.getAttributeTypeInfo(parent.getNodeName(),
362 getNodeName());
363 if (info != null && "ID".equals(info.type))
365 return true;
368 DomElement element = (DomElement) parent;
369 if (element.userIdAttrs != null &&
370 element.userIdAttrs.contains(this))
372 return true;
374 // TODO XML Schema implementation
376 return false;