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
.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
;
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>
81 private boolean specified
;
82 private String value
; // string value cache
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
);
105 // XXX register self to get insertion/removal events
106 // and character data change events and when they happen,
107 // report self-mutation
112 * Returns the attribute name (same as getNodeName)
114 public final String
getName()
116 return getNodeName();
121 * Returns true if a parser reported this was in the source text.
123 public final boolean getSpecified()
129 * Records whether this attribute was in the source text.
131 public final void setSpecified(boolean value
)
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
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
)
156 buf
.append(ctx
.getNodeValue());
158 case Node
.ENTITY_REFERENCE_NODE
:
163 return buf
.toString();
168 * Assigns the value of the attribute; it will have one child,
169 * which is a text node with the specified value (same as
172 public final void setValue(String value
)
179 * Returns the value of the attribute as a non-null string; same
181 * <em>NOTE: entity refs as children aren't currently handled.</em>
183 public final String
getValue()
185 return getNodeValue();
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
)
198 throw new DomDOMException(DOMException
.NO_MODIFICATION_ALLOWED_ERR
);
204 String oldValue
= getNodeValue();
209 // don't create a new node just for this...
211 Node text = owner.createTextNode(value);
218 mutating(oldValue
, value
, MutationEvent
.MODIFICATION
);
221 public final Node
getFirstChild()
223 // Create a child text node if necessary
227 Node text
= owner
.createTextNode((value
== null) ?
"" : value
);
233 public final Node
getLastChild()
235 // Create a child text node if necessary
239 Node text
= owner
.createTextNode((value
== null) ?
"" : value
);
245 public Node
item(int index
)
247 // Create a child text node if necessary
251 Node text
= owner
.createTextNode((value
== null) ?
"" : value
);
254 return super.item(index
);
259 * Returns the element with which this attribute is associated.
261 public final Element
getOwnerElement()
263 return (Element
) parent
;
266 public final Node
getNextSibling()
271 public final Node
getPreviousSibling()
276 public Node
getParentNode()
282 * Records the element with which this attribute is associated.
284 public final void setOwnerElement(Element e
)
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()
307 * Shallow clone of the attribute, breaking all ties with any
310 public Object
clone()
312 DomAttr retval
= (DomAttr
) super.clone();
313 retval
.specified
= true;
317 private void mutating(String oldValue
, String newValue
, short why
)
319 if (!reportMutations
|| parent
== null)
324 // EVENT: DOMAttrModified, target = parent,
325 // prev/new values provided, also attr name
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()
341 // DTD implementation
342 DomDoctype doctype
= (DomDoctype
) parent
.owner
.getDoctype();
345 return doctype
.getAttributeTypeInfo(parent
.getNodeName(),
348 // TODO XML Schema implementation
353 public boolean isId()
357 DomDoctype doctype
= (DomDoctype
) parent
.owner
.getDoctype();
360 DTDAttributeTypeInfo info
=
361 doctype
.getAttributeTypeInfo(parent
.getNodeName(),
363 if (info
!= null && "ID".equals(info
.type
))
368 DomElement element
= (DomElement
) parent
;
369 if (element
.userIdAttrs
!= null &&
370 element
.userIdAttrs
.contains(this))
374 // TODO XML Schema implementation