- /*
 - * $Id: AttributeNode.java,v 1.11 2001/04/11 02:27:56 edwingo Exp $
 - *
 - * The Apache Software License, Version 1.1
 - *
 - *
 - * Copyright (c) 2000 The Apache Software Foundation. All rights
 - * reserved.
 - *
 - * Redistribution and use in source and binary forms, with or without
 - * modification, are permitted provided that the following conditions
 - * are met:
 - *
 - * 1. Redistributions of source code must retain the above copyright
 - * notice, this list of conditions and the following disclaimer.
 - *
 - * 2. Redistributions in binary form must reproduce the above copyright
 - * notice, this list of conditions and the following disclaimer in
 - * the documentation and/or other materials provided with the
 - * distribution.
 - *
 - * 3. The end-user documentation included with the redistribution,
 - * if any, must include the following acknowledgment:
 - * "This product includes software developed by the
 - * Apache Software Foundation (http://www.apache.org/)."
 - * Alternately, this acknowledgment may appear in the software itself,
 - * if and wherever such third-party acknowledgments normally appear.
 - *
 - * 4. The names "Crimson" and "Apache Software Foundation" must
 - * not be used to endorse or promote products derived from this
 - * software without prior written permission. For written
 - * permission, please contact apache@apache.org.
 - *
 - * 5. Products derived from this software may not be called "Apache",
 - * nor may "Apache" appear in their name, without prior written
 - * permission of the Apache Software Foundation.
 - *
 - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 - * SUCH DAMAGE.
 - * ====================================================================
 - *
 - * This software consists of voluntary contributions made by many
 - * individuals on behalf of the Apache Software Foundation and was
 - * originally based on software copyright (c) 1999, Sun Microsystems, Inc.,
 - * http://www.sun.com. For more information on the Apache Software
 - * Foundation, please see <http://www.apache.org/>.
 - */
 - package org.apache.crimson.tree;
 - import java.io.Writer;
 - import java.io.IOException;
 - import org.w3c.dom.*;
 - import org.apache.crimson.util.XmlNames;
 - /**
 - * Node representing an XML attribute. Many views of attributes can be
 - * useful, but only the first of these is explicitly supported: <DL>
 - *
 - * <DT> <em>Logical View</em> </DT><DD> Attributes always hold a
 - * string created by expanding character and entity references from
 - * source text conforming to the XML specification. If this
 - * attribute was declared in a DTD, normalization will often be
 - * done to eliminate insignificant whitespace.</DD>
 - *
 - * <DT> <em>DTD Validated View</em> </DT><DD> If the attribute was
 - * declared in a DTD, it will have minimal semantics provided by its
 - * declaration, and checked by validating parsers. For example, the
 - * logical view may name one (or many) unparsed entities or DOM nodes.
 - * This view could provide direct access to them for any DTD, since
 - * these attribute semantics are defined by XML itself.</DD>
 - *
 - * <DT> <em>Semantic View</em> </DT><DD> The person who wrote the
 - * DTD (or other namespace) defined what each attribute's logical
 - * view "means". For example, that it's a URL, or that the unparsed
 - * entity referred to identifies a particular database to be used.
 - * This view would provide direct access to such values, but would
 - * need to have code specialized to that DTD or namespace.</DD>
 - *
 - * <DT> <em>Physical View</em> </DT><DD> Attributes may have children
 - * to represent text and entity reference nodes found in unexpanded
 - * and unnormalized XML source text. Such views are mostly of interest
 - * when editing XML text that is not dynamically generated by programs.
 - * This implementation does not currently support physical views of
 - * attributes. </DD>
 - *
 - * </DL>
 - *
 - *
 - * @author David Brownell
 - * @author Rajiv Mordani
 - * @version $Revision: 1.11 $
 - */
 - public class AttributeNode extends NamespacedNode implements Attr
 - {
 - private String value;
 - private boolean specified;
 - private String defaultValue;
 - /** At construction time ownerElement is null, it gets set whenever an
 - attribute is set on an Element */
 - private Element ownerElement;
 - /** Constructs an attribute node. Used for SAX2 and DOM2 */
 - public AttributeNode(String namespaceURI, String qName,
 - String value, boolean specified, String defaultValue)
 - throws DOMException
 - {
 - super(namespaceURI, qName);
 - this.value = value;
 - this.specified = specified;
 - this.defaultValue = defaultValue;
 - }
 - /**
 - * Make a clone of this node and return it. Used for cloneNode().
 - */
 - AttributeNode makeClone() {
 - AttributeNode retval = new AttributeNode(namespaceURI, qName, value,
 - specified, defaultValue);
 - retval.ownerDocument = ownerDocument;
 - return retval;
 - }
 - /**
 - * Package private method to check arguments for constructor
 - */
 - static void checkArguments(String namespaceURI, String qualifiedName)
 - throws DomEx
 - {
 - // [6] QName ::= (Prefix ':')? LocalPart
 - // [7] Prefix ::= NCName
 - // [8] LocalPart ::= NCName
 - if (qualifiedName == null) {
 - throw new DomEx(DomEx.NAMESPACE_ERR);
 - }
 - int first = qualifiedName.indexOf(':');
 - if (first <= 0) {
 - // no Prefix, only check LocalPart
 - if (!XmlNames.isUnqualifiedName(qualifiedName)) {
 - throw new DomEx(DomEx.INVALID_CHARACTER_ERR);
 - }
 - if ("xmlns".equals(qualifiedName) &&
 - !XmlNames.SPEC_XMLNS_URI.equals(namespaceURI)) {
 - throw new DomEx(DomEx.NAMESPACE_ERR);
 - }
 - return;
 - }
 - // Prefix exists, check everything
 - int last = qualifiedName.lastIndexOf(':');
 - if (last != first) {
 - throw new DomEx(DomEx.NAMESPACE_ERR);
 - }
 - String prefix = qualifiedName.substring(0, first);
 - String localName = qualifiedName.substring(first + 1);
 - if (!XmlNames.isUnqualifiedName(prefix)
 - || !XmlNames.isUnqualifiedName(localName)) {
 - throw new DomEx(DomEx.INVALID_CHARACTER_ERR);
 - }
 - // If we get here then we must have a valid prefix
 - if (namespaceURI == null
 - || ("xml".equals(prefix)
 - && !XmlNames.SPEC_XML_URI.equals(namespaceURI))) {
 - throw new DomEx(DomEx.NAMESPACE_ERR);
 - }
 - }
 - // package private
 - String getDefaultValue ()
 - {
 - return defaultValue;
 - }
 - /**
 - * <b>DOM2:</b>
 - */
 - public Element getOwnerElement() {
 - return ownerElement;
 - }
 - // package private
 - void setOwnerElement(Element element) {
 - if (element != null && ownerElement != null) {
 - throw new IllegalStateException(getMessage("A-000",
 - new Object[] { element.getTagName() }));
 - }
 - ownerElement = element;
 - }
 - /** DOM: Returns the ATTRIBUTE_NODE node type constant. */
 - public short getNodeType () { return ATTRIBUTE_NODE; }
 - /** DOM: Returns the attribute name */
 - public String getName () { return qName; }
 - /** DOM: Returns the attribute value. */
 - public String getValue () { return value; }
 - /** DOM: Assigns the value of this attribute. */
 - public void setValue (String value) { setNodeValue (value); }
 - /** DOM: Returns the attribute value. */
 - public String getNodeValue () { return value; }
 - /** DOM: Returns true if the source text specified the attribute. */
 - public boolean getSpecified () { return specified; }
 - /** DOM: Assigns the value of this attribute. */
 - public void setNodeValue (String value)
 - {
 - if (isReadonly ())
 - throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
 - this.value = value;
 - specified = true;
 - }
 - /** Flags whether the source text specified the attribute. */
 - // pubic
 - void setSpecified (boolean specified) { this.specified = specified; }
 - /** DOM: Returns null */
 - public Node getParentNode () { return null; }
 - /** DOM: Returns null */
 - public Node getNextSibling () { return null; }
 - /** DOM: Returns null */
 - public Node getPreviousSibling () { return null; }
 - /**
 - * Writes the attribute out, as if it were assigned within an
 - * element's starting tag (<em>name="value"</em>).
 - */
 - public void writeXml (XmlWriteContext context) throws IOException
 - {
 - Writer out = context.getWriter ();
 - out.write (qName);
 - out.write ("=\"");
 - writeChildrenXml (context);
 - out.write ('"');
 - }
 - /**
 - * Writes the attribute's value.
 - */
 - public void writeChildrenXml (XmlWriteContext context) throws IOException
 - {
 - Writer out = context.getWriter ();
 - for (int i = 0; i < value.length (); i++) {
 - int c = value.charAt (i);
 - switch (c) {
 - // XXX only a few of these are necessary; we
 - // do what "Canonical XML" expects
 - case '<': out.write ("<"); continue;
 - case '>': out.write (">"); continue;
 - case '&': out.write ("&"); continue;
 - case '\'': out.write ("'"); continue;
 - case '"': out.write ("""); continue;
 - default: out.write (c); continue;
 - }
 - }
 - }
 - /**
 - * DOM: returns a copy of this node which is not owned by an Element
 - */
 - public Node cloneNode(boolean deep) {
 - AttributeNode attr = cloneAttributeNode(deep);
 - // DOM says specified should be true
 - attr.specified = true;
 - return attr;
 - }
 - /**
 - * Clone this AttributeNode and possibly its children (which cannot be
 - * AttributeNodes themselves). "ownerElement" will remain null.
 - */
 - AttributeNode cloneAttributeNode(boolean deep) {
 - try {
 - AttributeNode attr = makeClone();
 - if (deep) {
 - Node node;
 - for (int i = 0; (node = item (i)) != null; i++) {
 - node = node.cloneNode (true);
 - attr.appendChild (node);
 - }
 - }
 - return attr;
 - } catch (DOMException e) {
 - throw new RuntimeException (getMessage ("A-002"));
 - }
 - }
 - void checkChildType(int type) throws DOMException {
 - switch(type) {
 - case TEXT_NODE:
 - case ENTITY_REFERENCE_NODE:
 - return;
 - default:
 - throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
 - }
 - }
 - }