All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javanet.staxutils.helpers.ElementContext Maven / Gradle / Ivy

The newest version!
/*
 * $Id: ElementContext.java,v 1.1 2004/07/15 02:13:54 cniles Exp $
 * 
 * Copyright (c) 2004, Christian Niles, unit12.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *		*   Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 * 
 *	    *	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.
 * 
 *      *   Neither the name of Christian Niles, Unit12, nor the names of its
 *          contributors may be used to endorse or promote products derived from
 *          this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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.
 * 
 */
package javanet.staxutils.helpers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;

import javanet.staxutils.SimpleNamespaceContext;

/**
 * Encapsulates access to contextual element information, such as the element name,
 * attributes, and namespaces. This class is useful for recording element information
 * in a stack to keep track of the current element c[position in a document.
 * 
 * @author Christian Niles
 * @version $Revision: 1.1 $
 */
public class ElementContext extends SimpleNamespaceContext {

    /** The element name. */
    private QName name;

    /** The encapsulating context. */
    private ElementContext parent;

    /** Ordered list of attributes. */
    private List attributeNames;

    /** Attribute values, keyed by their names. */
    private Map attributes;

    /** Ordered list of namespace prefixes. */
    private List namespacePrefixes;

    /** Whether the element is an empty element or not. */
    private boolean isEmpty;

    /** Whether the context has been closed for further edits. */
    private boolean readOnly;

    /**
     * Constructs a new ElementContext with the provided name and no
     * enclosing context.
     * 
     * @param name The element name.
     */
    public ElementContext(QName name) {

        this.name = name;

    }

    /**
     * Constructs a new ElementContext with the provided name and empty
     * value, and no enclosing context.
     * 
     * @param name The element name.
     * @param isEmpty Whether the element is an empty element or not.
     */
    public ElementContext(QName name, boolean isEmpty) {

        this.name = name;
        this.isEmpty = isEmpty;

    }

    /**
     * Constructs a new ElementContext with the provided name and
     * namespace context.
     * 
     * @param name The element name.
     * @param context The enclosing namespace context.
     */
    public ElementContext(QName name, NamespaceContext context) {

        super(context);
        this.name = name;

    }

    /**
     * Constructs a new ElementContext with the provided name and
     * enclosing context.
     * 
     * @param name The element name.
     * @param parent The enclosing element context.
     */
    public ElementContext(QName name, ElementContext parent) {

        super(parent);
        this.name = name;
        this.parent = parent;

    }

    /**
     * Constructs a new ElementContext with the provided name and
     * enclosing context.
     * 
     * @param name The element name.
     * @param parent The enclosing element context.
     * @param isEmpty Whether the element is an empty element or not.
     */
    public ElementContext(QName name, ElementContext parent, boolean isEmpty) {

        super(parent);
        this.name = name;
        this.parent = parent;
        this.isEmpty = isEmpty;

    }

    /**
     * Returns a reference to the enclosing ElementContext.
     * 
     * @return The enclosing context, or null.
     */
    public ElementContext getParentContext() {

        return parent;

    }

    /**
     * Determines if this context has an enclosing context or not.
     * 
     * @return true if this context is the root context and has no
     * 		enclosing context, false otherwise.
     */
    public boolean isRoot() {

        return parent == null;

    }

    /**
     * Returns the qualified name associated with the context.
     * 
     * @return The qualified name of the context.
     */
    public QName getName() {

        return name;

    }

    /**
     * Returns the current context path.
     * 
     * @return A string representing the context path.
     */
    public String getPath() {

        return appendPath(new StringBuffer()).toString();

    }

    /**
     * @see #getPath()
     */
    public String toString() {

        return getPath();

    }

    /**
     * Appends the current context path to a {@link StringBuffer}.
     * 
     * @param buffer The buffer to which to append the context path.
     * @return The provided buffer.
     */
    public StringBuffer appendPath(StringBuffer buffer) {

        if (parent != null) {

            parent.appendPath(buffer);

        }
        return buffer.append('/').append(name);

    }

    /**
     * Determines the number of enclosing contexts.
     * 
     * @return The number of enclosing contexts.
     */
    public int getDepth() {

        if (parent == null) {

            return 0;

        } else {

            return parent.getDepth() + 1;

        }

    }

    /**
     * Constructs a new child ElementContext with the specified name.
     * 
     * @param name The name associated with the child context.
     * @return The newly constructed child context.
     * @throws IllegalStateException If this context is empty.
     */
    public ElementContext newSubContext(QName name) {

        if (!isEmpty()) {

            return new ElementContext(name, this);

        } else {
            
            throw new IllegalStateException("ElementContext is empty");
            
        }
        
    }

    /**
     * Constructs a new child ElementContext with the specified name
     * and empty value.
     * 
     * @param name The name associated with the child context.
     * @param isEmpty Whether the child context represents an empty element.
     * @return The newly constructed child context.
     * @throws IllegalStateException If this context is empty.
     */
    public ElementContext newSubContext(QName name, boolean isEmpty) {

        if (!isEmpty()) {

            return new ElementContext(name, this, isEmpty);

        } else {
            
            throw new IllegalStateException("ElementContext is empty");
            
        }

    }

    /**
     * Adds an attribute to the context with the specified name and value.
     * 
     * @param name The attribute name.
     * @param value The attribute value.
     * @throws IllegalStateException If the context is read-only.
     */
    public void putAttribute(QName name, String value) {

        if (isReadOnly()) {

            throw new IllegalStateException("ElementContext is readOnly");

        } else if (attributes == null) {

            attributes = new HashMap();
            attributeNames = new ArrayList();

        }

        attributeNames.add(name);
        attributes.put(name, value);

    }

    /**
     * Adds a namespace declaration to this context with the specified prefix and
     * namespace uri.
     * 
     * @param prefix The namespace prefix.
     * @param nsURI The namespace uri.
     */
    public void putNamespace(String prefix, String nsURI) {

        if (isReadOnly()) {

            throw new IllegalStateException("ElementContext is readOnly");

        }

        if (namespacePrefixes == null) {

            namespacePrefixes = new ArrayList();

        }

        if (prefix.length() == 0) {

            // default namespace
            namespacePrefixes.add(prefix);
            super.setDefaultNamespace(nsURI);

        } else {

            namespacePrefixes.add(prefix);
            super.setPrefix(prefix, nsURI);

        }

    }

    /**
     * Returns the number of attributes defined in this context.
     * 
     * @return The number of attributes defined in the context.
     */
    public int attributeCount() {

        if (attributes != null) {

            return attributes.size();

        } else {

            return 0;

        }

    }

    /**
     * Returns the value of the idxth attribute defined on
     * the context.
     * 
     * @param idx The zero-based index of the attribute value to retrieve.
     * @return The value of the idxth attribute defined on
     * 		the context.
     * @throws IndexOutOfBoundsException If the index is out of bounds.
     */
    public String getAttribute(int idx) {

        return getAttribute(getAttributeName(idx));

    }

    /**
     * Returns the name of the idxth attribute defined on
     * the context.
     * 
     * @param idx The zero-based index of the attribute name to retrieve.
     * @return The name of the idxth attribute defined on
     * 		the context.
     * @throws IndexOutOfBoundsException If the index is out of bounds.
     */
    public QName getAttributeName(int idx) {

        if (attributeNames != null) {

            return (QName) attributeNames.get(idx);

        } else {

            throw new IndexOutOfBoundsException("Attribute index " + idx
                    + " doesn't exist");

        }

    }

    /**
     * Returns the value of a named attribute.
     * 
     * @param name The name of the attribute value to retrieve.
     * @return The value of the named attribute, or null.
     */
    public String getAttribute(QName name) {

        if (attributes != null) {

            return (String) attributes.get(name);

        } else {

            return null;

        }

    }

    /**
     * Determines if an attribute with the specified name exists in this context.
     * 
     * @param name The name of the attribute.
     * @return true if an attribute with the specified name has been
     * 		defined in this context, false otherwise.
     */
    public boolean attributeExists(QName name) {

        if (attributes != null) {

            return attributes.containsKey(name);

        } else {

            return false;

        }

    }

    /**
     * Returns an {@link Iterator} over the names of all attributes defined in this
     * context. The returned iterator will not support the {@link Iterator#remove()}
     * operation.
     * 
     * @return An {@link Iterator} over the names of all attributes defined in this
     *     context.
     */
    public Iterator attributeNames() {

        if (attributeNames != null) {

            return Collections.unmodifiableList(attributeNames).iterator();

        } else {

            return Collections.EMPTY_LIST.iterator();

        }

    }

    /**
     * Determines the number of namespaces declared in this context.
     * 
     * @return The number of namespaces declared in this context.
     */
    public int namespaceCount() {

        if (namespacePrefixes != null) {

            return namespacePrefixes.size();

        } else {

            return 0;

        }

    }

    /**
     * Returns the URI of the idxth namespace declaration
     * defined in this context.
     * 
     * @param idx The index of the namespace URI to return.
     * @return The URI of the idxth namespace declaration
     * 		defined in this context.
     * @throws IndexOutOfBoundsException If the index is out of bounds.
     */
    public String getNamespaceURI(int idx) {

        return this.getNamespaceURI(getNamespacePrefix(idx));

    }

    /**
     * Returns the prefix of the idxth namespace declaration
     * defined in this context.
     * 
     * @param idx The index of the namespace prefix to return.
     * @return The prefix of the idxth namespace declaration
     * 		defined in this context.
     * @throws IndexOutOfBoundsException If the index is out of bounds.
     */
    public String getNamespacePrefix(int idx) {

        if (namespacePrefixes != null) {

            return (String) namespacePrefixes.get(idx);

        } else {

            throw new IndexOutOfBoundsException("Namespace index " + idx
                    + " doesn't exist");

        }

    }

    /**
     * Whether this context may be edited or not.
     * 
     * @return true if no additional modifications may be made to this
     * 		context, false otherwise.
     */
    public boolean isReadOnly() {

        return readOnly;

    }

    /**
     * Prevents any further additions to this context.
     */
    public void setReadOnly() {

        this.readOnly = true;

    }

    /**
     * Whether this context represents an emtpy element. Empty contexts may not
     * enclose any other contexts.
     * 
     * @return true if this context represents an emtpy element,
     * 		false otherwise.
     */
    public boolean isEmpty() {

        return isEmpty;

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy