/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.saaj;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPVersion;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import javax.xml.namespace.QName;
import javax.xml.soap.Detail;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPFaultElement;
import javax.xml.soap.SOAPHeader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class SOAPElementImpl<T extends OMElement> extends NodeImpl<Element,T> implements SOAPElement {
    private String encodingStyle;

    public SOAPElementImpl(T element) {
        super((Element)element, element);
    }

    /**
     * Adds an attribute with the specified name and value to this <code>SOAPElement</code> object.
     * <p/>
     *
     * @param name  a <code>Name</code> object with the name of the attribute
     * @param value a <code>String</code> giving the value of the attribute
     * @return the <code>SOAPElement</code> object into which the attribute was inserted
     * @throws SOAPException if there is an error in creating the Attribute
     */
    public SOAPElement addAttribute(Name name, String value) throws SOAPException {
        if (name.getURI() == null || name.getURI().trim().length() == 0) {
            target.setAttributeNS("", name.getLocalName(), value);
        } else {
            target.setAttributeNS(name.getURI(), name.getPrefix() + ":" + name.getLocalName(),
                                   value);
        }
        return this;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.Name)
      */
    public SOAPElement addChildElement(Name name) throws SOAPException {
        String prefix = name.getPrefix();
        return addChildElement(name.getLocalName(), "".equals(prefix) ? null : prefix,
                               name.getURI());
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.SOAPElement)
      */
    public SOAPElement addChildElement(SOAPElement soapElement) throws SOAPException {
        String namespaceURI = soapElement.getNamespaceURI();
        String prefix = soapElement.getPrefix();
        String localName = soapElement.getLocalName();

        SOAPElementImpl<OMElement> childEle;        
        if (namespaceURI == null || namespaceURI.trim().length() == 0) {
            childEle =  new SOAPElementImpl<OMElement>((OMElement)getOwnerDocument().createElementNS(null, localName));
        } else {
            omTarget.declareNamespace(namespaceURI, prefix);
            childEle =
                new SOAPElementImpl<OMElement>((OMElement)target.getOwnerDocument().createElementNS(namespaceURI,
                                                                                    localName));
        }
        
        for (Iterator iter = soapElement.getAllAttributes(); iter.hasNext();) {
            Name name = (Name)iter.next();
            childEle.addAttribute(name, soapElement.getAttributeValue(name));
        }

        for (Iterator iter = soapElement.getChildElements(); iter.hasNext();) {
            Object o = iter.next();
            if (o instanceof Text) {
                childEle.addTextNode(((Text)o).getData());
            } else {
                childEle.addChildElement((SOAPElement)o);
            }
        }

        if (namespaceURI != null && namespaceURI.trim().length() > 0) {
            childEle.omTarget.setNamespace(childEle.omTarget.declareNamespace(namespaceURI, prefix));
        }
        target.appendChild(childEle.target);
        childEle.setParentElement(this);
        return childEle;
    }

    /* (non-Javadoc)
    * @see javax.xml.soap.SOAPElement#addChildElement(java.lang.String, java.lang.String, java.lang.String)
    */
    public SOAPElement addChildElement(String localName, String prefix, String namespaceURI)
            throws SOAPException {
        if (prefix == null) {
            prefix = "";
        }
        SOAPElementImpl<OMElement> childEle = (SOAPElementImpl<OMElement>)getOwnerDocument().
                        createElementNS(namespaceURI, prefix.length() == 0 ? localName : prefix + ":" + localName);
    
        childEle.omTarget.setNamespace(prefix.length() == 0
                ? childEle.omTarget.declareDefaultNamespace(namespaceURI)
                : childEle.omTarget.declareNamespace(namespaceURI, prefix));
        target.appendChild(childEle.target);
        childEle.setParentElement(this);
        return childEle;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#addChildElement(java.lang.String, java.lang.String)
      */
    public SOAPElement addChildElement(String localName, String prefix) throws SOAPException {
        String namespaceURI = getNamespaceURI(prefix);

        if (namespaceURI == null) {
            throw new SOAPException("Namespace not declared for the give prefix: " + prefix);
        }

        return addChildElement(localName, prefix, namespaceURI);
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#addChildElement(java.lang.String)
      */
    public SOAPElement addChildElement(String localName) throws SOAPException {
        SOAPElementImpl<OMElement> childEle =
                (SOAPElementImpl<OMElement>)getOwnerDocument().createElementNS(null, localName);
        target.appendChild(childEle.target);
        childEle.setParentElement(this);
        return childEle;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#addNamespaceDeclaration(java.lang.String, java.lang.String)
      */
    public SOAPElement addNamespaceDeclaration(String prefix, String uri) throws SOAPException {
        if (uri == null) {
            uri = "";
        }
        if (prefix == null || prefix.length() == 0) {
            omTarget.declareDefaultNamespace(uri);
        } else {
            omTarget.declareNamespace(uri, prefix);
        }
        return this;
    }

    /**
     * Creates a new <code>Text</code> object initialized with the given <code>String</code> and
     * adds it to this <code>SOAPElement</code> object.
     *
     * @param text a <code>String</code> object with the textual content to be added
     * @return the <code>SOAPElement</code> object into which the new <code>Text</code> object was
     *         inserted
     * @throws SOAPException if there is an error in creating the new <code>Text</code> object
     */
    public SOAPElement addTextNode(String text) throws SOAPException {
        //OmElement.setText() will remove all the other text nodes that it contains
        //Therefore create a text node and add it
        //TODO: May need to address the situation where the prev sibling of the textnode itself is a textnode
        Text textNode = getOwnerDocument().createTextNode(text);
        appendChild(textNode);
        return this;
    }

    /**
     * Returns an iterator over all of the attribute names in this <CODE>SOAPElement</CODE> object.
     * The iterator can be used to get the attribute names, which can then be passed to the method
     * <CODE>getAttributeValue</CODE> to retrieve the value of each attribute.
     *
     * @return an iterator over the names of the attributes
     */
    public Iterator getAllAttributes() {
        final Iterator attribIter = omTarget.getAllAttributes();
        Collection attribName = new ArrayList();
        Attr attr;
        while (attribIter.hasNext()) {
            attr = (Attr)attribIter.next();
            PrefixedQName qname;
            if (attr.getNamespaceURI() == null || attr.getNamespaceURI().trim().length() == 0) {
                qname = new PrefixedQName(attr.getNamespaceURI(),
                                          attr.getName(),
                                          attr.getPrefix());
            } else {
                qname = new PrefixedQName(attr.getNamespaceURI(),
                                          attr.getLocalName(),
                                          attr.getPrefix());
            }
            attribName.add(qname);
        }
        return attribName.iterator();
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getAttributeValue(javax.xml.soap.Name)
      */
    public String getAttributeValue(Name name) {
        //This method is waiting on the finalization of the name for a method
        //in OMElement that returns a OMAttribute from an input QName
        final OMAttribute attribute = omTarget.getAttribute(new QName(name.getURI(),
                                                                     name.getLocalName(),
                                                                     name.getPrefix()));
        if (attribute == null) {
            return null;
        }
        return attribute.getAttributeValue();
    }

    /**
     * Returns an iterator over all the immediate content of this element. This includes
     * <CODE>Text</CODE> objects as well as <CODE>SOAPElement</CODE> objects.
     *
     * @return an iterator over <CODE>Text</CODE> and <CODE>SOAPElement</CODE> contained within this
     *         <CODE>SOAPElement</CODE> object
     */
    public Iterator getChildElements() {
        Iterator childIter = omTarget.getChildren();
        Collection childElements = new ArrayList();
        while (childIter.hasNext()) {
            childElements.add(toSAAJNode((org.w3c.dom.Node)childIter.next()));
        }
        return childElements.iterator();
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getChildElements(javax.xml.soap.Name)
      */
    public Iterator getChildElements(Name name) {
        QName qName = new QName(name.getURI(), name.getLocalName());
        Iterator<OMElement> childIter = omTarget.getChildrenWithName(qName);
        Collection childElements = new ArrayList();
        while (childIter.hasNext()) {
            childElements.add(toSAAJNode((org.w3c.dom.Node)childIter.next()));
        }
        return childElements.iterator();
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getElementName()
      */
    public Name getElementName() {
        QName qName = omTarget.getQName();
        return new PrefixedQName(qName.getNamespaceURI(),
                                 qName.getLocalPart(),
                                 qName.getPrefix());
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getEncodingStyle()
      */
    public String getEncodingStyle() {
        return this.encodingStyle;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getNamespacePrefixes()
      */
    public Iterator getNamespacePrefixes() {
        //Get all declared namespace, make a list of their prefixes and return an iterator over that list
        ArrayList prefixList = new ArrayList();
        Iterator nsIter = omTarget.getAllDeclaredNamespaces();
        while (nsIter.hasNext()) {
            Object o = nsIter.next();
            if (o instanceof org.apache.axiom.om.OMNamespace) {
                org.apache.axiom.om.OMNamespace ns = (org.apache.axiom.om.OMNamespace)o;
                prefixList.add(ns.getPrefix());
            }
        }
        return prefixList.iterator();
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getNamespaceURI(java.lang.String)
      */
    public String getNamespaceURI(String prefix) {
        OMNamespace ns = omTarget.findNamespaceURI(prefix);
        return ns != null ? ns.getNamespaceURI() : null;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#getVisibleNamespacePrefixes()
      */
    public Iterator getVisibleNamespacePrefixes() {
        //I'll recursively return all the declared namespaces till this node, including its parents etc.
        Iterator namespacesIter = omTarget.getAllDeclaredNamespaces();
        ArrayList returnList = new ArrayList();
        while (namespacesIter.hasNext()) {
            Object o = namespacesIter.next();
            if (o instanceof OMNamespace) {
                OMNamespace ns = (OMNamespace)o;
                if (ns.getPrefix() != null) {
                    returnList.add(ns.getPrefix());
                }
            }
        }
        //taken care of adding namespaces of this node.
        //now we have to take care of adding the namespaces that are in the scope till the level of
        //this nodes' parent.
        org.apache.axiom.om.OMContainer parent = omTarget.getParent();
        if (parent != null && parent instanceof org.apache.axiom.om.OMElement) {
            Iterator parentScopeNamespacesIter =
                    ((org.apache.axiom.om.OMElement)parent).getAllDeclaredNamespaces();
            while (parentScopeNamespacesIter.hasNext()) {
                Object o = parentScopeNamespacesIter.next();
                if (o instanceof OMNamespace) {
                    OMNamespace ns = (OMNamespace)o;
                    if (ns.getPrefix() != null) {
                        returnList.add(ns.getPrefix());
                    }
                }
            }
        }
        return returnList.iterator();
    }


    public SOAPElement addAttribute(QName qname, String value) throws SOAPException {
        if (qname.getNamespaceURI() == null || qname.getNamespaceURI().trim().length() == 0) {
            target.setAttribute(qname.getLocalPart(), value);
        } else {
            target.setAttributeNS(qname.getNamespaceURI(), qname.getPrefix() + ":" +
                    qname.getLocalPart(), value);
        }
        return this;
    }

    public SOAPElement addChildElement(QName qname) throws SOAPException {
        String prefix = qname.getPrefix();
        return addChildElement(qname.getLocalPart(), "".equals(prefix) ?
                null : prefix, qname.getNamespaceURI());
    }

    /**
     * Creates a QName whose namespace URI is the one associated with the parameter, prefix, in the
     * context of this SOAPElement. The remaining elements of the new QName are taken directly from
     * the parameters, localName and prefix.
     *
     * @param localName - a String containing the local part of the name. prefix - a String
     *                  containing the prefix for the name.
     * @return a QName with the specified localName and prefix, and with a namespace that is
     *         associated with the prefix in the context of this SOAPElement. This namespace will be
     *         the same as the one that would be returned by getNamespaceURI(String) if it were
     *         given prefix as its parameter.
     * @throws SOAPException - if the QName cannot be created.
     * @since SAAJ 1.3
     */
    public QName createQName(String localName, String prefix) throws SOAPException {
        String namespaceURI = getNamespaceURI(prefix);
        if (namespaceURI == null) {
            throw new SOAPException("Invalid prefix");
        } else {
            return new QName(namespaceURI, localName, prefix);
        }
    }

    public Iterator getAllAttributesAsQNames() {
        final Iterator attribIter = omTarget.getAllAttributes();
        Collection attributesAsQNames = new ArrayList();
        Attr attr;
        QName qname;
        while (attribIter.hasNext()) {
            attr = (Attr)attribIter.next();
            //Check : attr.getLocalName() | attr.getName()
            qname = new QName(attr.getNamespaceURI(), attr.getName(), attr.getPrefix());
            attributesAsQNames.add(qname);
        }
        return attributesAsQNames.iterator();
    }

    public String getAttributeValue(QName qname) {
        final OMAttribute attribute = omTarget.getAttribute(qname);
        if (attribute == null) {
            return null;
        }
        return attribute.getAttributeValue();
    }

    public Iterator getChildElements(QName qname) {
        Iterator<OMElement> childIter = omTarget.getChildrenWithName(qname);
        Collection childElements = new ArrayList();
        while (childIter.hasNext()) {
            childElements.add(toSAAJNode((org.w3c.dom.Node)childIter.next()));
        }
        return childElements.iterator();
    }

    public QName getElementQName() {
        return omTarget.getQName();
    }

    public boolean removeAttribute(QName qname) {
        org.apache.axiom.om.OMAttribute attr = omTarget.getAttribute(qname);
        if (attr != null) {
            omTarget.removeAttribute(attr);
            return true;
        }
        return false;
    }

    public SOAPElement setElementQName(QName newName) throws SOAPException {
        String localName = this.target.getLocalName();
        if (org.apache.axiom.soap.SOAPConstants.BODY_LOCAL_NAME.equals(localName)
                || org.apache.axiom.soap.SOAPConstants.HEADER_LOCAL_NAME.equals(localName)
                || org.apache.axiom.soap.SOAPConstants.SOAPENVELOPE_LOCAL_NAME .equals(localName)) {
            throw new SOAPException("changing this element name is not allowed");
        }
        OMNamespace omNamespace =
                omTarget.getOMFactory().createOMNamespace(newName.getNamespaceURI(), newName.getPrefix());
        this.omTarget.setNamespace(omNamespace);
        this.omTarget.setLocalName(newName.getLocalPart());
        return this;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#removeAttribute(javax.xml.soap.Name)
      */
    public boolean removeAttribute(Name name) {
        org.apache.axiom.om.OMAttribute attr = omTarget.getAttribute(new QName(name.getURI(),
                                                                              name.getLocalName(),
                                                                              name.getPrefix()));
        if (attr != null) {
            omTarget.removeAttribute(attr);
            return true;
        }
        return false;
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#removeContents()
      */
    public void removeContents() {
        //We will get all the children and iteratively call the detach() on all of 'em.
        Iterator childIter = omTarget.getChildElements();
        while (childIter.hasNext()) {
            childIter.next();
            childIter.remove();
        }
    }

    /* (non-Javadoc)
      * @see javax.xml.soap.SOAPElement#removeNamespaceDeclaration(java.lang.String)
      */
    public boolean removeNamespaceDeclaration(String prefix) {
        for (Iterator<OMNamespace> it = omTarget.getAllDeclaredNamespaces(); it.hasNext(); ) {
            if (it.next().getPrefix().equals(prefix)) {
                it.remove();
                return true;
            }
        }
        return false;
    }


    /**
     * Sets the encoding style for this SOAPElement object to one specified.
     *
     * @param encodingStyle - a String giving the encoding style
     * @throws IllegalArgumentException
     *          - if there was a problem in the encoding style being set. SOAPException - if setting
     *          the encodingStyle is invalid for this SOAPElement.
     */
    public void setEncodingStyle(String encodingStyle) throws SOAPException {
        if (((SOAPFactory)this.omTarget.getOMFactory()).getSOAPVersion() == SOAPVersion.SOAP11) {
            try {
                URI uri = new URI(encodingStyle);
                if (!(this instanceof SOAPEnvelope)) {
                    if (!encodingStyle.equals(SOAPConstants.URI_NS_SOAP_ENCODING)) {
                        throw new IllegalArgumentException(
                                "Invalid Encoding style : " + encodingStyle);
                    }
                }
                this.encodingStyle = encodingStyle;
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException("Invalid Encoding style : "
                        + encodingStyle + ":" + e);
            }
        } else if (((SOAPFactory)this.omTarget.getOMFactory()).getSOAPVersion() == SOAPVersion.SOAP12) {
            if (this instanceof SOAPHeader || this instanceof SOAPBody ||
                    this instanceof SOAPFault ||
                    this instanceof SOAPFaultElement || this instanceof SOAPEnvelope ||
                    this instanceof Detail) {
                throw new SOAPException("EncodingStyle attribute cannot appear in : " + this);
            }
        }
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getAttribute(java.lang.String)
      */
    public String getAttribute(String name) {
        return target.getAttribute(name);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getAttributeNode(java.lang.String)
      */
    public Attr getAttributeNode(String name) {
        return target.getAttributeNode(name);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getAttributeNodeNS(java.lang.String, java.lang.String)
      */
    public Attr getAttributeNodeNS(String namespaceURI, String localName) {
        return target.getAttributeNodeNS(namespaceURI, localName);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getAttributeNS(java.lang.String, java.lang.String)
      */
    public String getAttributeNS(String namespaceURI, String localName) {
        return target.getAttributeNS(namespaceURI, localName);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getElementsByTagName(java.lang.String)
      */
    public NodeList getElementsByTagName(String name) {
        return toSAAJNodeList(target.getElementsByTagName(name));
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getElementsByTagNameNS(java.lang.String, java.lang.String)
      */
    public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
        return toSAAJNodeList(target.getElementsByTagNameNS(namespaceURI, localName));
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#getTagName()
      */
    public String getTagName() {
        return target.getTagName();
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#hasAttribute(java.lang.String)
      */
    public boolean hasAttribute(String name) {
        return target.hasAttribute(name);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#hasAttributeNS(java.lang.String, java.lang.String)
      */
    public boolean hasAttributeNS(String namespaceURI, String localName) {
        return target.hasAttributeNS(namespaceURI, localName);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#removeAttribute(java.lang.String)
      */
    public void removeAttribute(String name) throws DOMException {
        target.removeAttribute(name);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#removeAttributeNode(org.w3c.dom.Attr)
      */
    public Attr removeAttributeNode(Attr attr) throws DOMException {
        return target.removeAttributeNode(attr);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#removeAttributeNS(java.lang.String, java.lang.String)
      */
    public void removeAttributeNS(String namespaceURI, String localName) throws DOMException {
        target.removeAttributeNS(namespaceURI, localName);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#setAttribute(java.lang.String, java.lang.String)
      */
    public void setAttribute(String name, String value) throws DOMException {
        target.setAttribute(name, value);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#setAttributeNode(org.w3c.dom.Attr)
      */
    public Attr setAttributeNode(Attr attr) throws DOMException {
        return target.setAttributeNode(attr);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#setAttributeNodeNS(org.w3c.dom.Attr)
      */
    public Attr setAttributeNodeNS(Attr attr) throws DOMException {
        return target.setAttributeNodeNS(attr);
    }

    /* (non-Javadoc)
      * @see org.w3c.dom.Element#setAttributeNS(java.lang.String, java.lang.String, java.lang.String)
      */
    public void setAttributeNS(String namespaceURI,
                               String qualifiedName, String value) throws DOMException {
        target.setAttributeNS(namespaceURI, qualifiedName, value);
    }

    /**
     * Returns the the value of the immediate child of this <code>Node</code> object if a child
     * exists and its value is text.
     *
     * @return a <code>String</code> with the text of the immediate child of this <code>Node</code>
     *         object if (1) there is a child and (2) the child is a <code>Text</code> object;
     *         <code>null</code> otherwise
     */
    public String getValue() {
        if (omTarget.getType() == OMNode.TEXT_NODE) {
            return omTarget.getText();
        } else if (omTarget.getType() == OMNode.ELEMENT_NODE) {
            final OMNode firstOMChild = omTarget.getFirstOMChild();
            if (firstOMChild instanceof Text) {
                return ((Text)firstOMChild).getData();
            } else if (firstOMChild instanceof SOAPElementImpl) {
                return ((SOAPElement)firstOMChild).getValue();
            }
        }
        return null;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

    /**
     * If this is a Text node then this method will set its value, otherwise it sets the value of
     * the immediate (Text) child of this node. The value of the immediate child of this node can be
     * set only if, there is one child node and that node is a Text node, or if there are no
     * children in which case a child Text node will be created.
     *
     * @param value the text to set
     * @throws IllegalStateException if the node is not a Text  node and either has more than one
     *                               child node or has a child node that is not a Text node
     */
    public void setValue(String value) {
        OMNode firstChild = omTarget.getFirstOMChild();
        if (firstChild == null) {
            try {
                this.addTextNode(value);
            } catch (SOAPException e) {
                throw new RuntimeException("Cannot add text node", e);
            }
        } else if (((org.w3c.dom.Node)firstChild).getNodeType() == javax.xml.soap.Node.TEXT_NODE
                && firstChild.getNextOMSibling() == null) {
            ((org.w3c.dom.Text)firstChild).setData(value);
        } else {
            throw new IllegalStateException("This node is not a Text  node and " +
                    "either has more than one child node or has a child " +
                    "node that is not a Text node");
        }
    }

    public String toString() {
        return target.toString();
    }
        
    protected void copyContents(SOAPElementImpl childEle, Node child) throws SOAPException {
        NamedNodeMap attributes = child.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++) {
            Attr node = (Attr)attributes.item(i);
            QName name;
            if (node.getPrefix() == null) {
                name = new QName(node.getNamespaceURI(), 
                                 node.getLocalName());
            } else {
                name = new QName(node.getNamespaceURI(), 
                                 node.getLocalName(),
                                 node.getPrefix());
            }
            childEle.addAttribute(name, node.getValue());
        }

        Node node;
        while ((node = child.getFirstChild()) != null) {
            childEle.appendChild(node);
        }
    }
}
