summaryrefslogtreecommitdiff
path: root/libjava/gnu/xml/dom/DomAttr.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/gnu/xml/dom/DomAttr.java')
-rw-r--r--libjava/gnu/xml/dom/DomAttr.java379
1 files changed, 379 insertions, 0 deletions
diff --git a/libjava/gnu/xml/dom/DomAttr.java b/libjava/gnu/xml/dom/DomAttr.java
new file mode 100644
index 00000000000..2890430e315
--- /dev/null
+++ b/libjava/gnu/xml/dom/DomAttr.java
@@ -0,0 +1,379 @@
+/* DomAttr.java --
+ Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.dom;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.events.MutationEvent;
+
+
+/**
+ * <p> "Attr" implementation. In DOM, attributes cost quite a lot of
+ * memory because their values are complex structures rather than just
+ * simple strings. To reduce your costs, avoid having more than one
+ * child of an attribute; stick to a single Text node child, and ignore
+ * even that by using the attribute's "nodeValue" property.</p>
+ *
+ * <p> As a bit of general advice, only look at attribute modification
+ * events through the DOMAttrModified event (sent to the associated
+ * element). Implementations are not guaranteed to report other events
+ * in the same order, so you're very likely to write nonportable code if
+ * you monitor events at the "children of Attr" level.</p>
+ *
+ * <p> At this writing, not all attribute modifications will cause the
+ * DOMAttrModified event to be triggered ... only the ones using the string
+ * methods (setNodeValue, setValue, and Element.setAttribute) to modify
+ * those values. That is, if you manipulate those children directly,
+ * elements won't get notified that attribute values have changed.
+ * The natural fix for that will report other modifications, but won't
+ * be able to expose "previous" attribute value; it'll need to be cached
+ * or something (at which point why bother using child nodes). </p>
+ *
+ * <p><em>You are strongly advised not to use "children" of any attribute
+ * nodes you work with.</em> </p>
+ *
+ * @author David Brownell
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class DomAttr
+ extends DomNsNode
+ implements Attr
+{
+
+ private boolean specified;
+ private String value; // string value cache
+
+ /**
+ * Constructs an Attr node associated with the specified document.
+ * The "specified" flag is initialized to true, since this DOM has
+ * no current "back door" mechanisms to manage default values so
+ * that every value must effectively be "specified".
+ *
+ * <p>This constructor should only be invoked by a Document as part of
+ * its createAttribute functionality, or through a subclass which is
+ * similarly used in a "Sub-DOM" style layer.
+ *
+ * @param owner The document with which this node is associated
+ * @param namespaceURI Combined with the local part of the name,
+ * this is used to uniquely identify a type of attribute
+ * @param name Name of this attribute, which may include a prefix
+ */
+ protected DomAttr(DomDocument owner, String namespaceURI, String name)
+ {
+ super(ATTRIBUTE_NODE, owner, namespaceURI, name);
+ specified = true;
+ length = 1;
+
+ // XXX register self to get insertion/removal events
+ // and character data change events and when they happen,
+ // report self-mutation
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns the attribute name (same as getNodeName)
+ */
+ public final String getName()
+ {
+ return getNodeName();
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns true if a parser reported this was in the source text.
+ */
+ public final boolean getSpecified()
+ {
+ return specified;
+ }
+
+ /**
+ * Records whether this attribute was in the source text.
+ */
+ public final void setSpecified(boolean value)
+ {
+ specified = value;
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns the attribute value, with character and entity
+ * references substituted.
+ * <em>NOTE: entity refs as children aren't currently handled.</em>
+ */
+ public String getNodeValue()
+ {
+ // If we have a simple node-value, use that
+ if (first == null)
+ {
+ return (value == null) ? "" : value;
+ }
+ // Otherwise collect child node-values
+ StringBuffer buf = new StringBuffer();
+ for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ {
+ switch (ctx.nodeType)
+ {
+ case Node.TEXT_NODE:
+ buf.append(ctx.getNodeValue());
+ break;
+ case Node.ENTITY_REFERENCE_NODE:
+ // TODO
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Assigns the value of the attribute; it will have one child,
+ * which is a text node with the specified value (same as
+ * setNodeValue).
+ */
+ public final void setValue(String value)
+ {
+ setNodeValue(value);
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns the value of the attribute as a non-null string; same
+ * as getNodeValue.
+ * <em>NOTE: entity refs as children aren't currently handled.</em>
+ */
+ public final String getValue()
+ {
+ return getNodeValue();
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Assigns the attribute value; using this API, no entity or
+ * character references will exist.
+ * Causes a DOMAttrModified mutation event to be sent.
+ */
+ public void setNodeValue(String value)
+ {
+ if (readonly)
+ {
+ throw new DomEx(DomEx.NO_MODIFICATION_ALLOWED_ERR);
+ }
+ if (value == null)
+ {
+ value = "";
+ }
+ String oldValue = getNodeValue();
+ while (last != null)
+ {
+ removeChild(last);
+ }
+ // don't create a new node just for this...
+ /*
+ Node text = owner.createTextNode(value);
+ appendChild(text);
+ */
+ this.value = value;
+ length = 1;
+ specified = true;
+
+ mutating(oldValue, value, MutationEvent.MODIFICATION);
+ }
+
+ public final Node getFirstChild()
+ {
+ // Create a child text node if necessary
+ if (first == null)
+ {
+ length = 0;
+ Node text = owner.createTextNode((value == null) ? "" : value);
+ appendChild(text);
+ }
+ return first;
+ }
+
+ public final Node getLastChild()
+ {
+ // Create a child text node if necessary
+ if (last == null)
+ {
+ length = 0;
+ Node text = owner.createTextNode((value == null) ? "" : value);
+ appendChild(text);
+ }
+ return last;
+ }
+
+ public Node item(int index)
+ {
+ // Create a child text node if necessary
+ if (first == null)
+ {
+ length = 0;
+ Node text = owner.createTextNode((value == null) ? "" : value);
+ appendChild(text);
+ }
+ return super.item(index);
+ }
+
+ /**
+ * <b>DOM L2</b>
+ * Returns the element with which this attribute is associated.
+ */
+ public final Element getOwnerElement()
+ {
+ return (Element) parent;
+ }
+
+ public final Node getNextSibling()
+ {
+ return null;
+ }
+
+ public final Node getPreviousSibling()
+ {
+ return null;
+ }
+
+ public Node getParentNode()
+ {
+ return null;
+ }
+
+ /**
+ * Records the element with which this attribute is associated.
+ */
+ public final void setOwnerElement(Element e)
+ {
+ if (parent != null)
+ {
+ throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
+ }
+ if (!(e instanceof DomElement))
+ {
+ throw new DomEx(DomEx.WRONG_DOCUMENT_ERR);
+ }
+ parent = (DomElement) e;
+ depth = parent.depth + 1;
+ }
+
+ /**
+ * The base URI of an Attr is always <code>null</code>.
+ */
+ public final String getBaseURI()
+ {
+ return null;
+ }
+
+ /**
+ * Shallow clone of the attribute, breaking all ties with any
+ * elements.
+ */
+ public Object clone()
+ {
+ DomAttr retval = (DomAttr) super.clone();
+ retval.specified = true;
+ return retval;
+ }
+
+ private void mutating(String oldValue, String newValue, short why)
+ {
+ if (!reportMutations || parent == null)
+ {
+ return;
+ }
+
+ // EVENT: DOMAttrModified, target = parent,
+ // prev/new values provided, also attr name
+ MutationEvent event;
+
+ event = (MutationEvent) createEvent ("MutationEvents");
+ event.initMutationEvent ("DOMAttrModified",
+ true /* bubbles */, false /* nocancel */,
+ null, oldValue, newValue, getNodeName (), why);
+ parent.dispatchEvent (event);
+ }
+
+ // DOM Level 3 methods
+
+ public TypeInfo getSchemaTypeInfo()
+ {
+ if (parent != null)
+ {
+ // DTD implementation
+ DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
+ if (doctype != null)
+ {
+ return doctype.getAttributeTypeInfo(parent.getNodeName(),
+ getNodeName());
+ }
+ // TODO XML Schema implementation
+ }
+ return null;
+ }
+
+ public boolean isId()
+ {
+ if (parent != null)
+ {
+ DomDoctype doctype = (DomDoctype) parent.owner.getDoctype();
+ if (doctype != null)
+ {
+ DTDAttributeTypeInfo info =
+ doctype.getAttributeTypeInfo(parent.getNodeName(),
+ getNodeName());
+ if (info != null && "ID".equals(info.type))
+ {
+ return true;
+ }
+ }
+ DomElement element = (DomElement) parent;
+ if (element.userIdAttrs != null &&
+ element.userIdAttrs.contains(this))
+ {
+ return true;
+ }
+ // TODO XML Schema implementation
+ }
+ return false;
+ }
+
+}
+