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)
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
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
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. */
40 import org.w3c.dom.Attr;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.TypeInfo;
44 import org.w3c.dom.events.MutationEvent;
48 * <p> "Attr" implementation. In DOM, attributes cost quite a lot of
49 * memory because their values are complex structures rather than just
50 * simple strings. To reduce your costs, avoid having more than one
51 * child of an attribute; stick to a single Text node child, and ignore
52 * even that by using the attribute's "nodeValue" property.</p>
54 * <p> As a bit of general advice, only look at attribute modification
55 * events through the DOMAttrModified event (sent to the associated
56 * element). Implementations are not guaranteed to report other events
57 * in the same order, so you're very likely to write nonportable code if
58 * you monitor events at the "children of Attr" level.</p>
60 * <p> At this writing, not all attribute modifications will cause the
61 * DOMAttrModified event to be triggered ... only the ones using the string
62 * methods (setNodeValue, setValue, and Element.setAttribute) to modify
63 * those values. That is, if you manipulate those children directly,
64 * elements won't get notified that attribute values have changed.
65 * The natural fix for that will report other modifications, but won't
66 * be able to expose "previous" attribute value; it'll need to be cached
67 * or something (at which point why bother using child nodes). </p>
69 * <p><em>You are strongly advised not to use "children" of any attribute
70 * nodes you work with.</em> </p>
72 * @author David Brownell
73 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
80 private boolean specified;
81 private String value; // string value cache
84 * Constructs an Attr node associated with the specified document.
85 * The "specified" flag is initialized to true, since this DOM has
86 * no current "back door" mechanisms to manage default values so
87 * that every value must effectively be "specified".
89 * <p>This constructor should only be invoked by a Document as part of
90 * its createAttribute functionality, or through a subclass which is
91 * similarly used in a "Sub-DOM" style layer.
93 * @param owner The document with which this node is associated
94 * @param namespaceURI Combined with the local part of the name,
95 * this is used to uniquely identify a type of attribute
96 * @param name Name of this attribute, which may include a prefix
98 protected DomAttr(DomDocument owner, String namespaceURI, String name)
100 super(ATTRIBUTE_NODE, owner, namespaceURI, name);
104 // XXX register self to get insertion/removal events
105 // and character data change events and when they happen,
106 // report self-mutation
111 * Returns the attribute name (same as getNodeName)
113 public final String getName()
115 return getNodeName();
120 * Returns true if a parser reported this was in the source text.
122 public final boolean getSpecified()
128 * Records whether this attribute was in the source text.
130 public final void setSpecified(boolean value)
137 * Returns the attribute value, with character and entity
138 * references substituted.
139 * <em>NOTE: entity refs as children aren't currently handled.</em>
141 public String getNodeValue()
143 // If we have a simple node-value, use that
146 return (value == null) ? "" : value;
148 // Otherwise collect child node-values
149 StringBuffer buf = new StringBuffer();
150 for (DomNode ctx = first; ctx != null; ctx = ctx.next)
152 switch (ctx.nodeType)
155 buf.append(ctx.getNodeValue());
157 case Node.ENTITY_REFERENCE_NODE:
162 return buf.toString();
167 * Assigns the value of the attribute; it will have one child,
168 * which is a text node with the specified value (same as
171 public final void setValue(String value)
178 * Returns the value of the attribute as a non-null string; same
180 * <em>NOTE: entity refs as children aren't currently handled.</em>
182 public final String getValue()
184 return getNodeValue();
189 * Assigns the attribute value; using this API, no entity or
190 * character references will exist.
191 * Causes a DOMAttrModified mutation event to be sent.
193 public void setNodeValue(String value)
197 throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
203 String oldValue = getNodeValue();
208 // don't create a new node just for this...
210 Node text = owner.createTextNode(value);
217 mutating(oldValue, value, MutationEvent.MODIFICATION);
220 public final Node getFirstChild()
222 // Create a child text node if necessary
226 Node text = owner.createTextNode((value == null) ? "" : value);
232 public final Node getLastChild()
234 // Create a child text node if necessary
238 Node text = owner.createTextNode((value == null) ? "" : value);
244 public Node item(int index)
246 // Create a child text node if necessary
250 Node text = owner.createTextNode((value == null) ? "" : value);
253 return super.item(index);
258 * Returns the element with which this attribute is associated.
260 public final Element getOwnerElement()
262 return (Element) parent;
265 public final Node getNextSibling()
270 public final Node getPreviousSibling()
275 public Node getParentNode()
281 * Records the element with which this attribute is associated.
283 public final void setOwnerElement(Element e)
287 throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
289 if (!(e instanceof DomElement))
291 throw new DomEx(DomEx.WRONG_DOCUMENT_ERR);
293 parent = (DomElement) e;
294 depth = parent.depth + 1;
298 * The base URI of an Attr is always <code>null</code>.
300 public final String getBaseURI()
306 * Shallow clone of the attribute, breaking all ties with any
309 public Object clone()
311 DomAttr retval = (DomAttr) super.clone();
312 retval.specified = true;
316 private void mutating(String oldValue, String newValue, short why)
318 if (!reportMutations || parent == null)
323 // EVENT: DOMAttrModified, target = parent,
324 // prev/new values provided, also attr name
327 event = (MutationEvent) createEvent ("MutationEvents");
328 event.initMutationEvent ("DOMAttrModified",
329 true /* bubbles */, false /* nocancel */,
330 null, oldValue, newValue, getNodeName (), why);
331 parent.dispatchEvent (event);
334 // DOM Level 3 methods
336 public TypeInfo getSchemaTypeInfo()
340 // DTD implementation
341 DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
344 return doctype.getAttributeTypeInfo(parent.getNodeName(),
347 // TODO XML Schema implementation
352 public boolean isId()
356 DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
359 DTDAttributeTypeInfo info =
360 doctype.getAttributeTypeInfo(parent.getNodeName(),
362 if (info != null && "ID".equals(info.type))
367 DomElement element = (DomElement) parent;
368 if (element.userIdAttrs != null &&
369 element.userIdAttrs.contains(this))
373 // TODO XML Schema implementation