Package org.apache.axis2.om.impl.llom

Source Code of org.apache.axis2.om.impl.llom.OMElementImpl

/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* 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 org.apache.axis2.om.impl.llom;

import org.apache.axis2.om.*;
import org.apache.axis2.om.impl.llom.serialize.StreamWriterToContentHandlerConverter;
import org.apache.axis2.om.impl.llom.traverse.OMChildrenIterator;
import org.apache.axis2.om.impl.llom.traverse.OMChildrenQNameIterator;
import org.apache.axis2.om.impl.llom.util.EmptyIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.HashMap;
import java.util.Iterator;

/**
* Class OMElementImpl
*/
public class OMElementImpl extends OMNodeImpl
        implements OMElement, OMConstants {

    protected OMNamespace ns;

    /**
     * Field localName
     */
    protected String localName;
    /**
     * Field firstChild
     */
    protected OMNode firstChild;


    /**
     * Field namespaces
     */
    protected HashMap namespaces = null;

    /**
     * Field attributes
     */
    protected HashMap attributes = null;

    /**
     * Field log
     */
    private Log log = LogFactory.getLog(getClass());

    /**
     * Field noPrefixNamespaceCounter
     */
    protected int noPrefixNamespaceCounter = 0;
    private OMNode lastChild;

    /**
     * Constructor OMElementImpl
     *
     * @param localName
     * @param ns
     * @param parent
     * @param builder
     */
    public OMElementImpl(String localName, OMNamespace ns, OMContainer parent,
                         OMXMLParserWrapper builder) {
        super(parent);
        this.localName = localName;
        if (ns != null) {
            setNamespace(handleNamespace(ns));
        }
        this.builder = builder;
        firstChild = null;
    }

    /**
     * @param parent
     * @param parent
     */
    protected OMElementImpl(OMContainer parent) {
        super(parent);
        this.done = true;
    }

    /**
     * Constructor OMElementImpl
     *
     * @param localName
     * @param ns
     */
    public OMElementImpl(String localName, OMNamespace ns) {
        super(null);
        this.localName = localName;
        this.done = true;
        if (ns != null) {
            setNamespace(handleNamespace(ns));
        }
    }

    public OMElementImpl(String localName, OMNamespace ns, OMContainer parent) {
        super(parent);
        this.localName = localName;
        this.done = true;
        if (ns != null) {
            setNamespace(handleNamespace(ns));
        }
    }

    /**
     * Here it is assumed that this QName passed, at least contains the localName for this element
     *
     * @param qname
     * @param parent
     * @throws OMException
     */
    public OMElementImpl(QName qname, OMContainer parent) throws OMException {
        super(parent);
        this.localName = qname.getLocalPart();
        this.done = true;
        handleNamespace(qname, parent);
    }

    /**
     * Method handleNamespace
     *
     * @param qname
     * @param parent
     */
    private void handleNamespace(QName qname, OMContainer parent) {
        OMNamespace ns;

        // first try to find a namespace from the scope
        String namespaceURI = qname.getNamespaceURI();
        if (!"".equals(namespaceURI)) {
            ns = findNamespace(qname.getNamespaceURI(),
                    qname.getPrefix());
//        } else {
//            if (parent != null) {
//                ns = parent.getNamespace();
//            } else {
//                throw new OMException("Element can not be declared without a namespaceURI. Every Element should be namespace qualified");
//            }
//        }

            /**
             * What is left now is
             *  1. nsURI = null & parent != null, but ns = null
             *  2. nsURI != null, (parent doesn't have an ns with given URI), but ns = null
             */
            if ((ns == null) && !"".equals(namespaceURI)) {
                String prefix = qname.getPrefix();
                if (!"".equals(prefix)) {
                    ns = declareNamespace(namespaceURI, prefix);
                } else {
                    ns = declareNamespace(namespaceURI, getNextNamespacePrefix());
                }
            }
            if (ns != null) {
                this.setNamespace(ns);
//            throw new OMException("Element can not be declared without a namespaceURI. Every Element should be namespace qualified");

            }
        }
    }

    /**
     * Method handleNamespace
     *
     * @param ns
     * @return
     */
    private OMNamespace handleNamespace(OMNamespace ns) {
        OMNamespace namespace = findNamespace(ns.getName(),
                ns.getPrefix());
        if (namespace == null) {
            namespace = declareNamespace(ns);
        }
        return namespace;
    }

    /**
     * This will add child to the element. One can decide whether he append the child or he adds to the
     * front of the children list
     *
     * @param child
     */
    public void addChild(OMNode child) {
        addChild((OMNodeImpl) child);
    }

    /**
     * This will search for children with a given QName and will return an iterator to traverse through
     * the OMNodes.
     * This QName can contain any combination of prefix, localname and URI
     *
     * @param elementQName
     * @return
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public Iterator getChildrenWithName(QName elementQName) throws OMException {
        return new OMChildrenQNameIterator((OMNodeImpl) getFirstChild(),
                elementQName);
    }

    /**
     * Method getFirstChildWithName
     *
     * @param elementQName
     * @return
     * @throws OMException
     */
    public OMElement getFirstChildWithName(QName elementQName) throws OMException {
        OMChildrenQNameIterator omChildrenQNameIterator =
                new OMChildrenQNameIterator((OMNodeImpl) getFirstChild(),
                        elementQName);
        OMNode omNode = null;
        if (omChildrenQNameIterator.hasNext()) {
            omNode = (OMNode) omChildrenQNameIterator.next();
        }

        return ((omNode != null) && (OMNode.ELEMENT_NODE == omNode.getType())) ? (OMElement) omNode : null;

    }

    /**
     * Method addChild
     *
     * @param child
     */
    private void addChild(OMNodeImpl child) {
        if (firstChild == null) {
            firstChild = child;
            child.setPreviousSibling(null);
        } else {
            child.setPreviousSibling(lastChild);
            lastChild.setNextSibling(child);
        }
        child.setNextSibling(null);
        child.setParent(this);
        lastChild = child;

    }

    /**
     * This will give the next sibling. This can be an OMAttribute for OMAttribute or OMText or OMELement for others.
     *
     * @return
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public OMNode getNextSibling() throws OMException {
        while (!done) {
            builder.next();
        }
        return super.getNextSibling();
    }

    /**
     * This returns a collection of this element.
     * Children can be of types OMElement, OMText.
     *
     * @return
     */
    public Iterator getChildren() {
        return new OMChildrenIterator(getFirstChild());
    }

    /**
     * THis will create a namespace in the current element scope
     *
     * @param uri
     * @param prefix
     * @return
     */
    public OMNamespace declareNamespace(String uri, String prefix) {
        OMNamespaceImpl ns = new OMNamespaceImpl(uri, prefix);
        return declareNamespace(ns);
    }


    /**
     * @param namespace
     * @return
     */
    public OMNamespace declareNamespace(OMNamespace namespace) {
        if (namespaces == null) {
            this.namespaces = new HashMap(5);
        }
        namespaces.put(namespace.getPrefix(), namespace);
        return namespace;
    }

    /**
     * This will find a namespace with the given uri and prefix, in the scope of the docuemnt.
     * This will start to find from the current element and goes up in the hiararchy until this finds one.
     * If none is found, return null
     *
     * @param uri
     * @param prefix
     * @return
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public OMNamespace findNamespace(String uri, String prefix)
            throws OMException {

        // check in the current element
        OMNamespace namespace = findDeclaredNamespace(uri, prefix);
        if (namespace != null) {
            return namespace;
        }

        // go up to check with ancestors
        if (parent != null) {
            //Comment by Jaya:
            //For the OMDocument there won't be any explicit namespace
            //declarations, so going up the parent chain till the document
            //element should be enough.
            //If at a later point community decides that some standard
            //namespaces, like 'xml' which every XML w/ namespaces document
            //is supposed to contain implicitly, should go into OMDocument then
            //this 'if' block needs to be revisited.
            if (parent instanceof OMElement) {
                return ((OMElementImpl) parent).findNamespace(uri, prefix);
            }
        }
        return null;
    }

    /**
     * This will ckeck for the namespace <B>only</B> in the current Element
     * This can also be used to retrieve the prefix of a known namespace URI
     *
     * @param uri
     * @param prefix
     * @return
     * @throws OMException
     */
    private OMNamespace findDeclaredNamespace(String uri, String prefix)
            throws OMException {
        if (namespaces == null) {
            return null;
        }
        if (prefix == null || "".equals(prefix)) {
            Iterator namespaceListIterator = namespaces.values().iterator();
            while (namespaceListIterator.hasNext()) {
                OMNamespace omNamespace =
                        (OMNamespace) namespaceListIterator.next();
                if (omNamespace.getName().equals(uri)) {
                    return omNamespace;
                }
            }
            return null;
        } else {
            return (OMNamespace) namespaces.get(prefix);
        }
    }

    /**
     * Method getAllDeclaredNamespaces
     *
     * @return
     */
    public Iterator getAllDeclaredNamespaces() {
        if (namespaces == null) {
            return null;
        }
        return namespaces.values().iterator();
    }

    /**
     * This will help to search for an attribute with a given QName within this Element
     *
     * @param qname
     * @return
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public OMAttribute getFirstAttribute(QName qname) throws OMException {
        if (attributes == null) {
            return null;
        }
        return (OMAttribute) attributes.get(qname);
    }

    /**
     * This will return a List of OMAttributes
     *
     * @return
     */
    public Iterator getAttributes() {
        if (attributes == null) {
            return new EmptyIterator();
        }
        return attributes.values().iterator();
    }

    public Iterator getAttributes(QName qname) {
        //would there be multiple attributes with the same QName
        return null//ToDO
    }

    /**
     * This will insert attribute to this element. Implementor can decide as to insert this
     * in the front or at the end of set of attributes
     *
     * @param attr
     * @return
     */
    public OMAttribute addAttribute(OMAttribute attr) {
        if (attributes == null) {
            this.attributes = new HashMap(5);
        }
        attributes.put(attr.getQName(), attr);
        return attr;
    }

    /**
     * Method removeAttribute
     *
     * @param attr
     */
    public void removeAttribute(OMAttribute attr) {
        if (attributes != null) {
            attributes.remove(attr.getQName());
        }
    }

    /**
     * Method addAttribute
     *
     * @param attributeName
     * @param value
     * @param ns
     * @return
     */
    public OMAttribute addAttribute(String attributeName, String value,
                                    OMNamespace ns) {
        OMNamespace namespace = null;
        if (ns != null) {
            namespace = findNamespace(ns.getName(), ns.getPrefix());
            if (namespace == null) {
                throw new OMException("Given OMNamespace(" + ns.getName() + ns.getPrefix()
                        + ") for "
                        + "this attribute is not declared in the scope of this element. First declare the namespace"
                        + " and then use it with the attribute");
            }
        }
        return addAttribute(new OMAttributeImpl(attributeName, ns, value));
    }

    /**
     * Method setBuilder
     *
     * @param wrapper
     */
    public void setBuilder(OMXMLParserWrapper wrapper) {
        this.builder = wrapper;
    }

    /**
     * Method getBuilder
     *
     * @return
     */
    public OMXMLParserWrapper getBuilder() {
        return builder;
    }

    /**
     * This will force the parser to proceed, if parser has not yet finished with the XML input
     */
    public void buildNext() {
        builder.next();
    }

    /**
     * Method getFirstChild
     *
     * @return
     */
    public OMNode getFirstChild() {
        while ((firstChild == null) && !done) {
            buildNext();
        }
        return firstChild;
    }

    /**
     * Method setFirstChild
     *
     * @param firstChild
     */
    public void setFirstChild(OMNode firstChild) {
        this.firstChild = firstChild;
    }

    /**
     * This will remove this information item and its children, from the model completely
     *
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public OMNode detach() throws OMException {
        if (!done) {
            build();
        } else {
            super.detach();
        }
        return this;
    }

    /**
     * Method isComplete
     *
     * @return
     */
    public boolean isComplete() {
        return done;
    }

    /**
     * This is to get the type of node, as this is the super class of all the nodes
     *
     * @return
     * @throws org.apache.axis2.om.OMException
     * @throws OMException
     */
    public int getType() throws OMException {
        return OMNode.ELEMENT_NODE;
    }

    /**
     * @return
     * @see org.apache.axis2.om.OMElement#getXMLStreamReader()
     */
    public XMLStreamReader getXMLStreamReader() {
        return getXMLStreamReader(true);
    }

    /**
     * @return
     * @see org.apache.axis2.om.OMElement#getXMLStreamReaderWithoutCaching()
     */
    public XMLStreamReader getXMLStreamReaderWithoutCaching() {
        return getXMLStreamReader(false);
    }

    /**
     * @param cache
     * @return
     */
    private XMLStreamReader getXMLStreamReader(boolean cache) {
        if ((builder == null) && !cache) {
            throw new UnsupportedOperationException("This element was not created in a manner to be switched");
        }
        return new OMStAXWrapper(builder, this, cache);
    }

    /**
     * Sets the text of the given element.
     * caution - This method will wipe out all the text elements (and hence any
     * moxed content) before setting the text
     *
     * @param text
     */
    public void setText(String text) {

        OMNode child = this.getFirstChild();
        while (child != null) {
            if (child.getType() == OMNode.TEXT_NODE) {
                child.detach();
            }
            child = child.getNextSibling();
        }

        this.addChild(OMAbstractFactory.getOMFactory().createText(this, text));
    }

    /**
     * select all the text children and concat them to a single string
     *
     * @return
     */
    public String getText() {
        String childText = "";
        OMNode child = this.getFirstChild();
        OMText textNode = null;

        while (child != null) {
            if (child.getType() == OMNode.TEXT_NODE) {
                textNode = (OMText) child;
                if (textNode.getText() != null && !"".equals(textNode.getText().trim())) {
                    childText += textNode.getText().trim();
                }
            }
            child = child.getNextSibling();
        }

        return childText;
    }

    /**
     * Method serializeWithCache
     *
     * @param writer
     * @throws XMLStreamException
     */
    public void serializeWithCache(OMOutput omOutput) throws XMLStreamException {
        serialize(omOutput, true);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////

    protected void serialize(OMOutput omOutput, boolean cache) throws XMLStreamException {

        // select the builder
        short builderType = PULL_TYPE_BUILDER;    // default is pull type
        if (builder != null) {
            builderType = this.builder.getBuilderType();
        }
        if ((builderType == PUSH_TYPE_BUILDER)
                && (builder.getRegisteredContentHandler() == null)) {
            builder.registerExternalContentHandler(new StreamWriterToContentHandlerConverter(omOutput));
        }


        if (!cache) {
            //No caching
            if (this.firstChild != null) {
                OMSerializerUtil.serializeStartpart(this, omOutput);
                firstChild.serialize(omOutput);
                OMSerializerUtil.serializeEndpart(omOutput);
            } else if (!this.done) {
                if (builderType == PULL_TYPE_BUILDER) {
                    OMSerializerUtil.serializeByPullStream(this, omOutput);
                } else {
                    OMSerializerUtil.serializeStartpart(this, omOutput);
                    builder.setCache(cache);
                    builder.next();
                    OMSerializerUtil.serializeEndpart(omOutput);
                }
            } else {
                OMSerializerUtil.serializeNormal(this, omOutput, cache);
            }

            //serilize siblings
            if (this.nextSibling != null) {
                nextSibling.serialize(omOutput);
            } else if (this.parent != null) {
                if (!this.parent.isComplete()) {
                    builder.setCache(cache);
                    builder.next();
                }
            }
        } else {
            //Cached
            OMSerializerUtil.serializeNormal(this, omOutput, cache);
            // serialize the siblings
            OMNode nextSibling = this.getNextSibling();
            if (nextSibling != null) {
                nextSibling.serializeWithCache(omOutput);
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * This was requested during the second Axis2 summit. When one call this method, this will
     * serialize without building the object structure in the memory. Misuse of this method will
     * cause loss of data.So its adviced to use populateYourSelf() method, before this,
     * if you want to preserve data in the stream.
     *
     * @param omOutput
     * @throws XMLStreamException
     */
    public void serialize(OMOutput omOutput) throws XMLStreamException {
        this.serialize(omOutput, false);
    }


    /**
     * Method getNextNamespacePrefix
     *
     * @return
     */
    private String getNextNamespacePrefix() {
        return "ns" + ++noPrefixNamespaceCounter;
    }

    public OMElement getFirstElement() {
        OMNode node = getFirstChild();
        while (node != null) {
            if (node.getType() == OMNode.ELEMENT_NODE) {
                return (OMElement) node;
            } else {
                node = node.getNextSibling();
            }
        }
        return null;
    }

//    /* (non-Javadoc)
//    * @see org.apache.axis2.om.OMElement#getNextSiblingElement()
//    */
//    public OMElement getNextSiblingElement() throws OMException {
//        OMNode node = getNextSibling();
//        while(node != null){
//            if(node.getType() == OMNode.ELEMENT_NODE){
//                return (OMElement)node;
//            }else{
//                node = node.getNextSibling();
//            }
//        }
//        return null;
//    }


    /**
     * Method getLocalName
     *
     * @return
     */
    public String getLocalName() {
        return localName;
    }

    /**
     * Method setLocalName
     *
     * @param localName
     */
    public void setLocalName(String localName) {
        this.localName = localName;
    }

    /**
     * Method getNamespace
     *
     * @return
     * @throws OMException
     */
    public OMNamespace getNamespace() throws OMException {
//        if ((ns == null) && (parent != null)) {
//            ns = parent.getNamespace();
//        }
//        if (ns == null) {
//            throw new OMException("all elements in a soap message must be namespace qualified");
//        }
        return ns;
    }


    /**
     * @param namespace
     */
    public void setNamespace(OMNamespace namespace) {
        if (ns != null) {
            OMNamespace ns = this.findNamespace(namespace.getName(), namespace.getPrefix());
            if (ns == null) {
                ns = this.declareNamespace(namespace);
            }
        }
        this.ns = namespace;
    }

    /**
     * Method getQName
     *
     * @return
     */
    public QName getQName() {
        QName qName = null;

        if (ns != null) {
            if (ns.getPrefix() != null) {
                qName = new QName(ns.getName(), localName, ns.getPrefix());
            } else {
                qName = new QName(ns.getName(), localName);
            }
        } else {
            qName = new QName(localName);
        }
        return qName;
    }

    /**
     * Discard implementation for
     *
     * @throws OMException
     */
    public void discard() throws OMException {
        if (done) {
            this.detach();
        } else {
            builder.discard(this);
        }
    }
}
TOP

Related Classes of org.apache.axis2.om.impl.llom.OMElementImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.