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

com.googlecode.jinahya.xml.ElementLocator Maven / Gradle / Ivy

/*
 *  Copyright 2010 Jin Kwon.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */


package com.googlecode.jinahya.xml;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;


/**
 * Abstract element locator.
 *
 * @author Jin Kwon
 */
public abstract class ElementLocator {


    /**
     * Returns qualified name.
     *
     * @param node node
     * @param namespaces namespace map
     * @return qualified name
     */
    static String getQualifiedName(final ELNode node, final Map namespaces) {

        if (node == null) {
            throw new NullPointerException("null node");
        }

        if (namespaces == null) {
            throw new NullPointerException("null namespaceMap");
        }

        return getQualifiedName(node.getNamespaceURI(), node.getLocalName(),
                                namespaces);
    }


    /**
     * 
     * @param namespaceURI
     * @param localName
     * @param namespaces
     * @return 
     */
    static String getQualifiedName(final String namespaceURI,
                                   final String localName,
                                   final Map namespaces) {

        if (namespaceURI == null) {
            throw new NullPointerException("null namespaceURI");
        }

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        if (namespaces == null) {
            throw new NullPointerException("null namespaces");
        }

        if (ELNode.NULL_NS_URI.equals(namespaceURI)) {
            return localName;
        }

        final String namespacePrefix = (String) namespaces.get(namespaceURI);
        if (namespacePrefix == null) {
            throw new RuntimeException(
                "no namespace prefix for " + namespaceURI);
        }

        return namespacePrefix + ":" + localName;
    }


    /**
     * 
     * @param element
     * @return 
     */
    static Map getNamespaces(final ELElement element) {

        if (element == null) {
            throw new NullPointerException("null element");
        }

        final Map namespaces = new TreeMap();

        final Set namespaceURIs = element.getNamespaceURIs();
        for (Iterator i = namespaceURIs.iterator(); i.hasNext();) {
            namespaces.put(i.next(), null);
        }

        int index = 0;
        for (Iterator i = namespaceURIs.iterator(); i.hasNext();) {
            namespaces.put(i.next(), "ns" + index);
            index++;
        }

        namespaces.put(ELNode.XML_NS_URI, ELNode.XML_NS_PREFIX);

        return namespaces;
    }


    /**
     * Creates a new instance.
     *
     * @param root root element
     */
    public ElementLocator(final ELElement root) {
        super();

        if (root == null) {
            throw new NullPointerException("null root");
        }

        path.add(root);
    }


    /**
     * 
     * @return 
     */
    public final String getNamespaceURI() {

        return getCurrent().getNamespaceURI();
    }


    /**
     * 
     * @return 
     */
    public final String getLocalName() {

        return getCurrent().getLocalName();
    }


    /**
     * Returns the number of child elements which each has given
     * localName in no namespace.
     *
     * @param localName local name
     * @return number of children
     */
    public final int getChildCount(final String localName) {

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        return getChildCount(ELNode.NULL_NS_URI, localName);
    }


    /**
     * Returns the number of child elements which each has given
     * localName in specified namespaceURI. En empty
     * string("") must be used for no(null) namespace.
     *
     * @param namespaceURI The namespace URI.
     * @param localName The local name.
     * @return child count
     * @see #getCount(String) 
     */
    public final int getChildCount(final String namespaceURI,
                                   final String localName) {

        int count = 0;

        for (Iterator i = getCurrent().getElements().iterator(); i.hasNext();) {
            final ELElement child = (ELElement) i.next();
            if (!child.getLocalName().equals(localName)) {
                continue;
            }
            if (!child.getNamespaceURI().equals(namespaceURI)) {
                continue;
            }
            count++;
        }

        return count;
    }


    /**
     * Locate to the root element. Nothing happens if this locator is already
     * locating the root element.
     *
     * @return self
     */
    public final ElementLocator locateRoot() {

        while (path.size() > 1) {
            path.remove(path.size() - 1);
        }

        return this;
    }


    /**
     * Locates to the parent element.
     * 
     * @return self
     */
    public final ElementLocator locateParent() {

        if (path.size() > 1) {
            path.remove(path.size() - 1);
        }

        return this;
    }


    /**
     * Locates child element which has given localName in no
     * namespace at index. An
     * IndexOutOfBoundsException will be thrown if there is no
     * child at specified index.
     *
     * @param localName element's local name
     * @param index child element index
     * @return self
     * @see #child(java.lang.String, java.lang.String, int)
     */
    public final ElementLocator locateChild(final String localName,
                                            final int index) {

        return locateChild(ELNode.NULL_NS_URI, localName, index);
    }


    /**
     * Locate a child element which has given localName in given
     * namespaceURI at index. An
     * IndexOutOfBoundsException will be thrown if there is no
     * child at specified index.
     *
     * @param namespaceURI element's namespace URI
     * @param localName element's local name
     * @param index target index to locate
     * @return self
     * @see #child(String, int) 
     */
    public final ElementLocator locateChild(final String namespaceURI,
                                            final String localName,
                                            final int index) {

        if (namespaceURI == null) {
            throw new NullPointerException("null namespaceURI");
        }

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        if (index < 0) {
            throw new IllegalArgumentException("negative index: " + index);
        }

        int count = 0;
        for (Iterator i = getCurrent().getElements().iterator(); i.hasNext();) {
            final ELElement element = (ELElement) i.next();
            if (!element.getLocalName().equals(localName)) {
                continue;
            }
            if (!element.getNamespaceURI().equals(namespaceURI)) {
                continue;
            }
            if (count == index) {
                path.add(element);
                return this;
            }
            count++;
        }

        throw new IndexOutOfBoundsException("no child at " + index);
    }


    /**
     * Adds a child element and locate it. The new child element will be named
     * as localName in no namespace.
     *
     * @param localName new child element's local name.
     * @return self
     */
    public final ElementLocator addChild(final String localName) {

        return addChild(ELNode.NULL_NS_URI, localName);
    }


    /**
     * Adds a child element and locate it. The new child element will be named
     * as localName in given namespaceURI.
     *
     * @param namespaceURI child element's namespace URI
     * @param localName child element's local name
     * @return self
     */
    public final ElementLocator addChild(final String namespaceURI,
                                         final String localName) {

        final ELElement child = new ELElement(namespaceURI, localName);

        getCurrent().getElements().add(child);

        path.add(child);

        return this;
    }


    /**
     * Returns text value of currently located element.
     *
     * @return text value; may be null
     */
    public final String getText() {
        return getCurrent().getText();
    }


    /**
     * Sets the text value of currently located element.
     * 
     * @param text new text value
     * @return self
     */
    public final ElementLocator setText(final String text) {

        getCurrent().setText(text);

        return this;
    }


    public final String getAttribute(final String localName) {

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        return getAttribute(ELNode.NULL_NS_URI, localName);
    }


    /**
     * Finds an attribute and returns its value.
     *
     * @param namespaceURI attribute's namespace URI
     * @param localName attribute's local name
     * @return attribute's value or null if not found
     */
    public final String getAttribute(final String namespaceURI,
                                     final String localName) {

        if (namespaceURI == null) {
            throw new NullPointerException("null namespaceURI");
        }

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        final ELAttribute attribute =
            (ELAttribute) getCurrent().getAttributes().get(
            ELNode.jamesClark(namespaceURI, localName));

        if (attribute == null) {
            return null;
        }

        return attribute.getValue();
    }


    public final ElementLocator setAttribute(final String localName,
                                             final String value) {

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        return setAttribute(ELNode.NULL_NS_URI, localName, value);
    }


    /**
     * Sets or removes attribute's value. If value is null mapped
     * attribute will be removed.
     *
     * @param namespaceURI attribute's namespace URI
     * @param localName attribute's local name
     * @param value attribute's value; null for removing attribute
     * @return self
     */
    public final ElementLocator setAttribute(final String namespaceURI,
                                             final String localName,
                                             final String value) {

        if (namespaceURI == null) {
            throw new NullPointerException("null namespaceURI");
        }

        if (localName == null) {
            throw new NullPointerException("null localName");
        }

        if (localName.trim().isEmpty()) {
            throw new IllegalArgumentException("empty localName");
        }

        final String expressed = ELNode.jamesClark(namespaceURI, localName);

        if (value == null) {
            getCurrent().getAttributes().remove(expressed);
            return this;
        }

        final ELAttribute attribute =
            new ELAttribute(namespaceURI, localName, value);

        getCurrent().getAttributes().put(expressed, attribute);

        return this;
    }


    /**
     * Removes currently located element and locate parent. An
     * IllegalStateException will be thrown if this locate is
     * currently locating the root element.
     *
     * @return self
     */
    public final ElementLocator removeCurrent() {

        if (path.size() == 1) {
            throw new IllegalStateException("can't remove the root element");
        }

        final ELElement element = getCurrent();

        locateParent().getCurrent().getElements().remove(element);

        return this;
    }


    /**
     * Returns currently located element.
     *
     * @return current element
     */
    final ELElement getCurrent() {
        return (ELElement) path.get(path.size() - 1);
    }


    /**
     * Returns the root element.
     *
     * @return the root element
     */
    final ELElement getRoot() {
        return (ELElement) path.get(0);
    }


    /** element path. */
    private final List path = new ArrayList();
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy