/*
 * Copyright 2001-2004 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.axis.message;

import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.encoding.DeserializationContext;
import org.apache.axis.encoding.Deserializer;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.encoding.TextSerializationContext;
import org.apache.axis.constants.Style;
import org.apache.axis.soap.SOAPConstants;
import org.apache.axis.utils.Mapping;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.XMLUtils;
import org.apache.commons.logging.Log;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import javax.xml.namespace.QName;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

/**
 * MessageElement is the base type of nodes of the SOAP message parse tree.
 *
 * Note: it was made Serializable to help users of Apache SOAP who had
 * exploited the serializability of the DOM tree to migrate to Axis.
 * @todo implement the NodeList methods properly, with tests. 
 */
public class MessageElement extends NodeImpl implements SOAPElement,
        Serializable,
        org.w3c.dom.NodeList,  // ADD Nodelist Interfaces for SAAJ 1.2
        Cloneable
{
    protected static Log log =
        LogFactory.getLog(MessageElement.class.getName());

    private static final Mapping enc11Mapping =
            new Mapping(Constants.URI_SOAP11_ENC,
                        "SOAP-ENC");

    private static final Mapping enc12Mapping =
            new Mapping(Constants.URI_SOAP12_ENC,
                        "SOAP-ENC");

    protected String    id;
    protected String    href;
    protected boolean   _isRoot = true;
    protected SOAPEnvelope message = null;

    protected transient DeserializationContext context;

    protected transient QName typeQName = null;

    protected Vector qNameAttrs = null;

    // Some message representations - as recorded SAX events...
    protected transient SAX2EventRecorder recorder = null;
    protected int startEventIndex = 0;
    protected int startContentsIndex = 0;
    protected int endEventIndex = -1;

    public ArrayList namespaces = null;

    /** Our encoding style, if any */
    protected String encodingStyle = null;

    /** Object value, possibly supplied by subclass */
    private Object objectValue = null;

    /** No-arg constructor for building messages?
     */
    public MessageElement()
    {
    }

    /**
     * constructor
     * @param namespace namespace of element
     * @param localPart local name
     */
    public MessageElement(String namespace, String localPart)
    {
        namespaceURI = namespace;
        name = localPart;
    }

    /**
     * constructor. Automatically adds a namespace-prefix mapping to the mapping table
     * @param localPart local name
     * @param prefix prefix
     * @param namespace namespace
     */
    public MessageElement(String localPart, String prefix, String namespace)
    {
        this.namespaceURI = namespace;
        this.name = localPart;
        this.prefix = prefix;
        addMapping(new Mapping(namespace, prefix));
    }

    /**
     * construct using a {@link javax.xml.soap.Name} implementation,
     * @see #MessageElement(String, String, String)
     * @param eltName
     */
    public MessageElement(Name eltName)
    {
        this(eltName.getLocalName(),eltName.getPrefix(), eltName.getURI());
    }

    /**
     * constructor binding the internal object value field to the
     * value parameter
     * @param namespace namespace of the element
     * @param localPart local name
     * @param value value of the node
     */
    public MessageElement(String namespace, String localPart, Object value)
    {
        this(namespace, localPart);
        objectValue = value;
    }

    /**
     * constructor declaring the qualified name of the node
     * @param name naming information
     */
    public MessageElement(QName name)
    {
        this(name.getNamespaceURI(), name.getLocalPart());
    }

    /**
     * constructor declaring the qualified name of the node
     * and its value
     * @param name naming information
     * @param value value of the node
     */
    public MessageElement(QName name, Object value)
    {
        this(name.getNamespaceURI(), name.getLocalPart());
        objectValue = value;
    }

    /**
     * create a node through a deep copy of the passed in element.
     * @param elem name to copy from
     */
    public MessageElement(Element elem)
    {
        namespaceURI = elem.getNamespaceURI();
        name = elem.getLocalName();
        copyNode(elem);
    }

    /**
     * construct a text element.
     * @param text text data. This is <i>not</i> copied; it is referred to in the MessageElement.
     */
    public MessageElement(CharacterData text)
    {
        textRep = text;
        namespaceURI = text.getNamespaceURI();
        name = text.getLocalName();
    }

    /**
     * Advanced constructor used for deserialization.
     * <ol>
     * <li>The context provides the mappings and Sax event recorder
     * <li>The soap messaging style is determined from the current message context, defaulting
     * to SOAP1.1 if there is no current context.
     * <li>if there is an id attribute (any namespace), then the ID is registered
     * with {@link DeserializationContext#registerElementByID(String, MessageElement)} ;a  new recorder is
     * created if needed.
     * <li>If there is an attribute "root" in the default SOAP namespace, then it is examined
     * to see if it marks the element as root (value=="1" or not)
     * <li>If there is an arrayType attribute then we assume we are an array and set our
     * {@link #typeQName} field appropriately.
     * <li>The {@link #href} field is set if there is a relevant href value
     * </ol>
     *
     * @param namespace namespace namespace of element
     * @param localPart local name local name of element
     * @param prefix prefix prefix of element
     * @param attributes attributes to save as our attributes
     * @param context deserialization context for this message element
     * @throws AxisFault if the encoding style is not recognized/supported
     */
    public MessageElement(String namespace, String localPart, String prefix,
                   Attributes attributes, DeserializationContext context)
        throws AxisFault
    {
        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("newElem00", super.toString(),
                                            "{" + prefix + "}" + localPart));
            for (int i = 0; attributes != null && i < attributes.getLength(); i++) {
                log.debug("  " + attributes.getQName(i) + " = '" + attributes.getValue(i) + "'");
            }
        }
        this.namespaceURI = namespace;
        this.name = localPart;
        this.prefix = prefix;

        this.context = context;
        this.startEventIndex = context.getStartOfMappingsPos();

        setNSMappings(context.getCurrentNSMappings());

        this.recorder = context.getRecorder();

        if (attributes != null && attributes.getLength() > 0) {
            this.attributes = attributes;

            this.typeQName = context.getTypeFromAttributes(namespace,
                                                      localPart,
                                                      attributes);

            String rootVal = attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ROOT);

            if (rootVal != null) {
                _isRoot = "1".equals(rootVal);
            }

            id = attributes.getValue(Constants.ATTR_ID);
            // Register this ID with the context.....
            if (id != null) {
                context.registerElementByID(id, this);
                if (recorder == null) {
                    recorder = new SAX2EventRecorder();
                    context.setRecorder(recorder);
                }
            }

            // Set the encoding style to the attribute value.  If null,
            // we just automatically use our parent's (see getEncodingStyle)
            MessageContext mc = context.getMessageContext();
            SOAPConstants sc = (mc != null) ?
                                            mc.getSOAPConstants() :
                                            SOAPConstants.SOAP11_CONSTANTS;

            href = attributes.getValue(sc.getAttrHref());

            // If there's an arrayType attribute, we can pretty well guess that we're an Array???
            if (attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ARRAY_TYPE) != null) {
                typeQName = Constants.SOAP_ARRAY;
            }


            encodingStyle =
                    attributes.getValue(sc.getEncodingURI(),
                                        Constants.ATTR_ENCODING_STYLE);

            // if no-encoding style was defined, we don't define as well
            if (Constants.URI_SOAP12_NOENC.equals(encodingStyle))
                encodingStyle = null;

            // If we have an encoding style, and are not a MESSAGE style
            // operation (in other words - we're going to do some data
            // binding), AND we're SOAP 1.2, check the encoding style against
            // the ones we've got type mappings registered for.  If it isn't
            // registered, throw a DataEncodingUnknown fault as per the
            // SOAP 1.2 spec.
            if (encodingStyle != null &&
                    sc.equals(SOAPConstants.SOAP12_CONSTANTS) &&
                    (mc.getOperationStyle() != Style.MESSAGE)) {
                TypeMapping tm = mc.getTypeMappingRegistry().
                        getTypeMapping(encodingStyle);
                if (tm == null ||
                        (tm.equals(mc.getTypeMappingRegistry().
                                                getDefaultTypeMapping()))) {
                    AxisFault badEncodingFault = new AxisFault(
                            Constants.FAULT_SOAP12_DATAENCODINGUNKNOWN,
                            "bad encoding style", null, null);
                    throw badEncodingFault;
                }
            }

        }
    }

    /**
     * Retrieve the DeserializationContext associated with this MessageElement
     *
     * @return The DeserializationContext associated with this MessageElement
     */
    public DeserializationContext getDeserializationContext()
    {
        return context;
    }

    /** !!! TODO : Make sure this handles multiple targets
     */
    protected Deserializer fixupDeserializer;

    public void setFixupDeserializer(Deserializer dser)
    {
        // !!! Merge targets here if already set?
        fixupDeserializer = dser;
    }

    public Deserializer getFixupDeserializer()
    {
        return fixupDeserializer;
    }

    /**
     * record the end index of the SAX recording.
     * @param endIndex end value
     */
    public void setEndIndex(int endIndex)
    {
        endEventIndex = endIndex;
        //context.setRecorder(null);
    }

    /**
     * get the is-root flag
     * @return true if the element is considered a document root.
     */
    public boolean isRoot() { return _isRoot; }

    /**
     * get a saved ID
     * @return ID or null for no ID
     */
    public String getID() { return id; }

    /**
     * get a saved href
     * @return href or null
     */
    public String getHref() { return href; }

    /**
     * get the attributes
     * @return attributes. If this equals {@link NullAttributes.singleton} it is null
     *
     */
    public Attributes getAttributesEx() { return attributes; }


    /**
     * Returns a duplicate of this node, i.e., serves as a generic copy
     * constructor for nodes. The duplicate node has no parent; (
     * <code>parentNode</code> is <code>null</code>.).
     * <br>Cloning an <code>Element</code> copies all attributes and their
     * values, including those generated by the XML processor to represent
     * defaulted attributes, but this method does not copy any text it
     * contains unless it is a deep clone, since the text is contained in a
     * child <code>Text</code> node. Cloning an <code>Attribute</code>
     * directly, as opposed to be cloned as part of an <code>Element</code>
     * cloning operation, returns a specified attribute (
     * <code>specified</code> is <code>true</code>). Cloning any other type
     * of node simply returns a copy of this node.
     * <br>Note that cloning an immutable subtree results in a mutable copy,
     * but the children of an <code>EntityReference</code> clone are readonly
     * . In addition, clones of unspecified <code>Attr</code> nodes are
     * specified. And, cloning <code>Document</code>,
     * <code>DocumentType</code>, <code>Entity</code>, and
     * <code>Notation</code> nodes is implementation dependent.
     *
     * @param deep If <code>true</code>, recursively clone the subtree under
     *             the specified node; if <code>false</code>, clone only the node
     *             itself (and its attributes, if it is an <code>Element</code>).
     * @return The duplicate node.
     */
    public Node cloneNode(boolean deep) {
        try{
            MessageElement clonedSelf = (MessageElement) cloning();

            if(deep){
                if(children != null){
                    for(int i =0; i < children.size(); i++){
                        NodeImpl child = (NodeImpl)children.get(i);
                        if(child != null) {  // why child can be null?
                            NodeImpl clonedChild = (NodeImpl)child.cloneNode(deep); // deep == true
                            clonedChild.setParent(clonedSelf);
                            clonedChild.setOwnerDocument(getOwnerDocument());
                            
                            clonedSelf.childDeepCloned( child, clonedChild );
                        }
                    }
                }
            }
            return clonedSelf;
        }
        catch(Exception e){
            return null;
        }
    }

    // Called when a child is cloned from cloneNode().
    //
    // This is used by sub-classes to update internal state when specific elements
    // are cloned.
    protected void childDeepCloned( NodeImpl oldNode, NodeImpl newNode )
    {
    }

    /**
     *  protected clone method (not public)
     *
     *  copied status
     *  -------------------
     *  protected String    name ;             Y
     *  protected String    prefix ;           Y
     *  protected String    namespaceURI ;     Y
     *  protected transient Attributes attributes  Y
     *  protected String    id;               Y?
     *  protected String    href;             Y?
     *  protected boolean   _isRoot = true;   Y?
     *  protected SOAPEnvelope message = null; N?
     *  protected transient DeserializationContext context;  Y?
     *  protected transient QName typeQName = null;          Y?
     *  protected Vector qNameAttrs = null;                  Y?
     *  protected transient SAX2EventRecorder recorder = null; N?
     *  protected int startEventIndex = 0;                   N?
     *  protected int startContentsIndex = 0;                N?
     *  protected int endEventIndex = -1;                    N?
     *  protected CharacterData textRep = null;             Y?
     *  protected MessageElement parent = null;             N
     *  public ArrayList namespaces = null;                 Y
     *  protected String encodingStyle = null;              N?
     *   private Object objectValue = null;                 N?
     *
     * @return
     * @throws CloneNotSupportedException
     */
    protected Object cloning() throws CloneNotSupportedException
    {
        try{
            MessageElement clonedME = null;
            clonedME = (MessageElement)this.clone();

            clonedME.setName(name);
            clonedME.setNamespaceURI(namespaceURI);
            clonedME.setPrefix(prefix);

            // new AttributesImpl will copy all data not set referencing only
            clonedME.setAllAttributes(new AttributesImpl(attributes));
            //       clonedME.addNamespaceDeclaration((namespaces.clone()); // cannot do this. since we cannot access the namepace arraylist

            clonedME.namespaces = new ArrayList();
            if(namespaces != null){
                for(int i = 0; i < namespaces.size(); i++){
                    //     jeus.util.Logger.directLog( " Debug :  namspace.size() = " + namespaces.size());
                    Mapping namespace = (Mapping)namespaces.get(i);
                    clonedME.addNamespaceDeclaration(namespace.getPrefix(), namespace.getNamespaceURI()); // why exception here!!
                }
            }
            clonedME.children = new ArrayList();

            // clear parents relationship to old parent
            clonedME.parent = null;
            // clonedME.setObjectValue(objectValue); // how to copy this???
            clonedME.setDirty(this._isDirty);
            if(encodingStyle != null){
                clonedME.setEncodingStyle(encodingStyle);
            }
            return clonedME;
        }catch(Exception ex){
            return null;
        }
    }


    /**
     * set all the attributes of this instance
     * @param attrs a new attributes list
     */
    public void setAllAttributes(Attributes attrs){
        attributes = attrs;
    }

    /**
     * remove all children.
     */
    public void detachAllChildren()
    {
        removeContents();
    }

    /**
     * Obtain an Attributes collection consisting of all attributes
     * for this MessageElement, including namespace declarations.
     *
     * @return Attributes collection
     */
    public Attributes getCompleteAttributes() {
        if (namespaces == null) {
            return attributes;
        }

        AttributesImpl attrs = null;
        if (attributes == NullAttributes.singleton) {
            attrs = new AttributesImpl();
        } else {
            attrs = new AttributesImpl(attributes);
        }

        for (Iterator iterator = namespaces.iterator(); iterator.hasNext();) {
            Mapping mapping = (Mapping) iterator.next();
            String prefix = mapping.getPrefix();
            String nsURI = mapping.getNamespaceURI();
            attrs.addAttribute(Constants.NS_URI_XMLNS, prefix,
                               "xmlns:" + prefix, nsURI, "CDATA");
        }
        return attrs;
    }

    /**
     * get the local name of this element
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * set the local part of this element's name
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * get the fully qualified name of this element
     * @return a QName describing the name of thsi element
     */
    public QName getQName() {
        return new QName(namespaceURI, name);
    }

    /**
     * set the name and namespace of this element
     * @param qName qualified name
     */
    public void setQName(QName qName) {
        this.name = qName.getLocalPart();
        this.namespaceURI = qName.getNamespaceURI();
    }

    /**
     * set the namespace URI of the element
     * @param nsURI new namespace URI
     */
    public void setNamespaceURI(String nsURI) {
        namespaceURI = nsURI;
    }

    /**
     * get the element's type.
     * If we are a reference, we look up our target in the context and
     * return (and cache) its type.
     * @return
     */
    public QName getType() {
        // Try to get the type from our target if we're a reference...
        if (typeQName == null && href != null && context != null) {
            MessageElement referent = context.getElementByID(href);
            if (referent != null) {
                typeQName = referent.getType();
            }
        }
        return typeQName;
    }

    /**
     * set the element's type
     * @param qname
     */
    public void setType(QName qname) {
        typeQName = qname;
    }

    /**
     * get the event recorder
     * @return recorder or null
     */
    public SAX2EventRecorder getRecorder() {
        return recorder;
    }

    /**
     * set the event recorder
     * @param rec
     */
    public void setRecorder(SAX2EventRecorder rec) {
        recorder = rec;
    }

    /**
     * Get the encoding style.  If ours is null, walk up the hierarchy
     * and use our parent's.  Default if we're the root is "".
     *
     * @return the currently in-scope encoding style
     */
    public String getEncodingStyle() {
        if (encodingStyle == null) {
            if (parent == null) {
                return "";
            }
            return ((MessageElement) parent).getEncodingStyle();
        }
        return encodingStyle;
    }

    /**
     * remove all chidlren.
     * All SOAPExceptions which can get thrown in this process are ignored.
     */
    public void removeContents() {
        // unlink
        if (children != null) {
            for (int i = 0; i < children.size(); i++) {
                try {
                    ((NodeImpl) children.get(i)).setParent(null);
                } catch (SOAPException e) {
                    log.debug("ignoring", e);
                }
            }
            // empty the collection
            children.clear();
            setDirty(true);
        }
    }

    /**
     * get an iterator over visible prefixes. This includes all declared in
     * parent elements
     * @return an iterator.
     */
    public Iterator getVisibleNamespacePrefixes() {
        Vector prefixes = new Vector();

        // Add all parents namespace definitions
        if(parent !=null){
            Iterator parentsPrefixes = ((MessageElement)parent).getVisibleNamespacePrefixes();
            if(parentsPrefixes != null){
                while(parentsPrefixes.hasNext()){
                    prefixes.add(parentsPrefixes.next());
                }
            }
        }
        Iterator mine = getNamespacePrefixes();
        if(mine != null){
            while(mine.hasNext()){
                prefixes.add(mine.next());
            }
        }
        return prefixes.iterator();
    }

    /**
     * Sets the encoding style for this <CODE>SOAPElement</CODE>
     * object to one specified. The semantics of a null value,
     * as above in getEncodingStyle() are to just use the parent's value,
     * but null here means set to "".
     *
     * @param   encodingStyle a <CODE>String</CODE>
     *     giving the encoding style
     * @throws  java.lang.IllegalArgumentException  if
     *     there was a problem in the encoding style being set.
     * @see #getEncodingStyle() getEncodingStyle()
     */
    public void setEncodingStyle(String encodingStyle) throws SOAPException {
        if (encodingStyle == null) {
            encodingStyle = "";
        }

        this.encodingStyle = encodingStyle;

        // Wherever we set the encoding style, map the SOAP-ENC prefix
        // just for fun (if it's a known style)
        if (encodingStyle.equals(Constants.URI_SOAP11_ENC)) {
            addMapping(enc11Mapping);
        } else if (encodingStyle.equals(Constants.URI_SOAP12_ENC)) {
            addMapping(enc12Mapping);
        }
    }

    /**
     * Note that this method will log a error and no-op if there is
     * a value (set using setObjectValue) in the MessageElement.
     */
    public void addChild(MessageElement el) throws SOAPException
    {
        if (objectValue != null) {
            IllegalStateException exc =
                new IllegalStateException(Messages.getMessage("valuePresent"));
            log.error(Messages.getMessage("valuePresent"), exc);
            throw exc;
        }
        initializeChildren();
        children.add(el);
        el.parent = this;
    }

    /**
     * get a list of children
     * @return a list, or null if there are no children
     */
    public List getChildren()
    {
        return children;
    }

    /**
     * set the index point of our content's starting in the
     * event recording
     * @param index index value of the first event of our recorder.
     */
    public void setContentsIndex(int index)
    {
        startContentsIndex = index;
    }

    /**
     * set a new namespace mapping list
     * @param namespaces
     */
    public void setNSMappings(ArrayList namespaces)
    {
        this.namespaces = namespaces;
    }

    /**
     * get the prefix for a given namespace URI
     * @param searchNamespaceURI namespace
     * @return null for null or emtpy uri, null for no match, and the prefix iff there is a match
     */
    public String getPrefix(String searchNamespaceURI) {
        if ((searchNamespaceURI == null) || ("".equals(searchNamespaceURI)))
            return null;

        if (href != null && getRealElement() != null) {
            return getRealElement().getPrefix(searchNamespaceURI);
        }

        for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
            Mapping map = (Mapping) namespaces.get(i);
            if (map.getNamespaceURI().equals(searchNamespaceURI)) {
                return map.getPrefix();
            }
        }

        if (parent != null) {
            return ((MessageElement) parent).getPrefix(searchNamespaceURI);
        }

        return null;
    }

    /**
     * map from a prefix to a namespace.
     * Will recurse <i>upward the element tree</i> until we get a match
     * @param searchPrefix
     * @return the prefix, or null for no match
     */
    public String getNamespaceURI(String searchPrefix) {
        if (searchPrefix == null) {
            searchPrefix = "";
        }

        if (href != null && getRealElement() != null) {
            return getRealElement().getNamespaceURI(searchPrefix);
        }

        for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
            Mapping map = (Mapping) namespaces.get(i);
            if (map.getPrefix().equals(searchPrefix)) {
                return map.getNamespaceURI();
            }
        }

        if (parent != null) {
            return ((MessageElement) parent).getNamespaceURI(searchPrefix);
        }

        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("noPrefix00", "" + this, searchPrefix));
        }

        return null;
    }

    /**
     * Returns value of the node as an object of registered type.
     * @return Object of proper type, or null if no mapping could be found.
     */
    public Object getObjectValue() {
        Object obj = null;
        try {
            obj = getObjectValue(null);
        } catch (Exception e) {
            log.debug("getValue()", e);
        }
        return obj;
    }

    /**
     * Returns value of the node as an object of registered type.
     * @param cls Class that contains top level deserializer metadata
     * @return Object of proper type, or null if no mapping could be found.
     */
    public Object getObjectValue(Class cls) throws Exception {
        if (objectValue == null) {
            objectValue = getValueAsType(getType(), cls);
        }
        return objectValue;
    }

    /**
     * Sets value of this node to an Object.
     * A serializer needs to be registered for this object class for proper
     * operation.
     * <p>
     * Note that this method will log an error and no-op if there are
     * any children in the MessageElement or if the MessageElement was
     * constructed from XML.
     * @param newValue node's value or null.
     */
    public void setObjectValue(Object newValue) throws SOAPException {
        if (children != null && !children.isEmpty()) {
            SOAPException exc = new SOAPException(Messages.getMessage("childPresent"));
            log.error(Messages.getMessage("childPresent"), exc);
            throw exc;
        }
        if (textRep != null) {
            SOAPException exc = new SOAPException(Messages.getMessage("xmlPresent"));
            log.error(Messages.getMessage("xmlPresent"), exc);
            throw exc;
        }
        this.objectValue = newValue;
    }

    public Object getValueAsType(QName type) throws Exception
    {
        return getValueAsType(type, null);
    }

    /**
     * This is deserialization logic mixed in to our element class.
     * It is only valid we have a deserializer, which means that we were created
     * using {@link MessageElement#MessageElement(String, String, String, org.xml.sax.Attributes, org.apache.axis.encoding.DeserializationContext)}
     * @param type type to look up a deserializer for.
     * @param cls class to use for looking up the deserializer. This takes precedence over the type field.
     * @return the value of the deserializer
     * @throws Exception
     */
    public Object getValueAsType(QName type, Class cls) throws Exception
    {
        if (context == null) {
            throw new Exception(Messages.getMessage("noContext00"));
        }

        Deserializer dser = null;
        if (cls == null) {
            dser = context.getDeserializerForType(type);
        } else {
            dser = context.getDeserializerForClass(cls);
        }
        if (dser == null) {
            throw new Exception(Messages.getMessage("noDeser00", "" + type));
        }

        boolean oldVal = context.isDoneParsing();
        context.deserializing(true);
        context.pushElementHandler(new EnvelopeHandler((SOAPHandler)dser));

        publishToHandler((org.xml.sax.ContentHandler) context);

        context.deserializing(oldVal);

        return dser.getValue();
    }

    /**
     * class that represents a qname in a the qNameAttrs vector.
     */
    protected static class QNameAttr {
        public QName name;
        public QName value;
    }

    /**
     * add an attribute to the qname vector. This is a separate vector from the
     * main attribute list.
     * @param namespace
     * @param localName
     * @param value
     */

    public void addAttribute(String namespace, String localName,
                             QName value)
    {
        if (qNameAttrs == null) {
            qNameAttrs = new Vector();
        }

        QNameAttr attr = new QNameAttr();
        attr.name = new QName(namespace, localName);
        attr.value = value;

        qNameAttrs.addElement(attr);
        // !!! Add attribute to attributes!
    }

    /**
     * add a normal CDATA/text attribute.
     * There is no check whether or not the attribute already exists.
     * @param namespace namespace URI
     * @param localName local anme
     * @param value value
     */
    public void addAttribute(String namespace, String localName,
                             String value)
    {
        AttributesImpl attributes = makeAttributesEditable();
        attributes.addAttribute(namespace, localName, "", "CDATA",
                                value);
    }

    /**
     * add an attribute.
     * Note that the prefix is not added to our mapping list.
     * Also, there is no check whether or not the attribute already exists.
     * @param attrPrefix prefix.
     * @param namespace namespace URI
     * @param localName
     * @param value
     */
    public void addAttribute(String attrPrefix, String namespace, String localName,
                             String value)
    {
        AttributesImpl attributes = makeAttributesEditable();
        String attrName = localName;
        if (attrPrefix != null && attrPrefix.length() > 0) {
            attrName = attrPrefix + ":" + localName;
        }
        attributes.addAttribute(namespace, localName, attrName, "CDATA",
                                value);
    }

    /**
     * Set an attribute, adding the attribute if it isn't already present
     * in this element, and changing the value if it is.  Passing null as the
     * value will cause any pre-existing attribute by this name to go away.
     */
    public void setAttribute(String namespace, String localName,
                             String value)
    {
        AttributesImpl attributes = makeAttributesEditable();

        int idx = attributes.getIndex(namespace, localName);
        if (idx > -1) {
            // Got it, so replace it's value.
            if (value != null) {
                attributes.setValue(idx, value);
            } else {
                attributes.removeAttribute(idx);
            }
            return;
        }

        addAttribute(namespace, localName, value);
    }

    /**
     * get the value of an attribute
     * @param localName
     * @return the value or null
     */
    public String getAttributeValue(String localName)
    {
        if (attributes == null) {
           return null;
        }
        return attributes.getValue(localName);
    }

    /**
     * bind a a new soap envelope. sets the dirty bit.
     * @param env
     */
    public void setEnvelope(SOAPEnvelope env)
    {
        env.setDirty(true);
        message = env;
    }

    /**
     * get our current envelope
     * @return envelope or null.
     */
    public SOAPEnvelope getEnvelope()
    {
        return message;
    }

    /**
     * get the 'real' element -will follow hrefs.
     * @return the message element or null if there is a href to something
     * that is not a MessageElemeent.
     */
    public MessageElement getRealElement()
    {
        if (href == null) {
            return this;
        }

        Object obj = context.getObjectByRef(href);
        if (obj == null) {
            return null;
        }

        if (!(obj instanceof MessageElement)) {
            return null;
        }

        return (MessageElement) obj;
    }

    /**
     * get the message element as a document.
     * This serializes the element to a string and then parses it.
     * @see #getAsString()
     * @return
     * @throws Exception
     */
    public Document getAsDocument() throws Exception
    {
        String elementString = getAsString();

        Reader reader = new StringReader(elementString);
        Document doc = XMLUtils.newDocument(new InputSource(reader));
        if (doc == null) {
            throw new Exception(
                    Messages.getMessage("noDoc00", elementString));
        }
        return doc;
    }

    /**
     * get the message element as a string.
     * This is not a cheap operation, as we have to serialise the
     * entire message element to the current context, then
     * convert it to a string.
     * Nor is it cached; repeated calls repeat the operation.
     * @return an XML fragment in a string.
     * @throws Exception if anything went wrong
     */
    public String getAsString() throws Exception {
        SerializationContext serializeContext = null;
        StringWriter writer = new StringWriter();
        MessageContext msgContext;
        if (context != null) {
            msgContext = context.getMessageContext();
        } else {
            msgContext = MessageContext.getCurrentContext();
        }
        serializeContext = new SerializationContext(writer, msgContext);
        serializeContext.setSendDecl(false);
        setDirty(false);
        output(serializeContext);
        writer.close();

        return writer.getBuffer().toString();
    }

    /**
     * create a DOM from the message element, by
     * serializing and deserializing the element
     * @see #getAsString()
     * @see #getAsDocument()
     * @return the root document element of the element
     * @throws Exception
     */
    public Element getAsDOM() throws Exception
    {
        return getAsDocument().getDocumentElement();
    }

    /**
     * replay the sax events to a handler
     * @param handler
     * @throws SAXException
     */
    public void publishToHandler(ContentHandler handler) throws SAXException
    {
        if (recorder == null) {
            throw new SAXException(Messages.getMessage("noRecorder00"));
        }

        recorder.replay(startEventIndex, endEventIndex, handler);
    }

    /**
     * replay the sax events to a SAX content handles
     * @param handler
     * @throws SAXException
     */
    public void publishContents(ContentHandler handler) throws SAXException
    {
        if (recorder == null) {
            throw new SAXException(Messages.getMessage("noRecorder00"));
        }

        recorder.replay(startContentsIndex, endEventIndex-1, handler);
    }

    /** This is the public output() method, which will always simply use
     * the recorded SAX stream for this element if it is available.  If
     * not, this method calls outputImpl() to allow subclasses and
     * programmatically created messages to serialize themselves.
     *
     * @param outputContext the SerializationContext we will write to.
     */
    public final void output(SerializationContext outputContext) throws Exception
    {
        if ((recorder != null) && (!_isDirty)) {
            recorder.replay(startEventIndex,
                            endEventIndex,
                            new SAXOutputter(outputContext));
            return;
        }

        // Turn QName attributes into strings
        if (qNameAttrs != null) {
            for (int i = 0; i < qNameAttrs.size(); i++) {
                QNameAttr attr = (QNameAttr)qNameAttrs.get(i);
                QName attrName = attr.name;
                setAttribute(attrName.getNamespaceURI(),
                             attrName.getLocalPart(),
                             outputContext.qName2String(attr.value));
            }
        }

        /**
         * Write the encoding style attribute IF it's different from
         * whatever encoding style is in scope....
         */
        if (encodingStyle != null) {
            MessageContext mc = outputContext.getMessageContext();
            SOAPConstants soapConstants = (mc != null) ?
                                            mc.getSOAPConstants() :
                                            SOAPConstants.SOAP11_CONSTANTS;
            if (parent == null) {
                // don't emit an encoding style if its "" (literal)
                if (!"".equals(encodingStyle)) {
                    setAttribute(soapConstants.getEnvelopeURI(),
                                 Constants.ATTR_ENCODING_STYLE,
                                 encodingStyle);
                }
            } else if (!encodingStyle.equals(((MessageElement)parent).getEncodingStyle())) {
                setAttribute(soapConstants.getEnvelopeURI(),
                             Constants.ATTR_ENCODING_STYLE,
                             encodingStyle);
            }
        }

        outputImpl(outputContext);
    }

    /**
     * override point -output to a serialization context.
     * @param outputContext destination.
     * @throws Exception if something went wrong.
     */
    protected void outputImpl(SerializationContext outputContext) throws Exception
    {
        if (textRep != null) {
            boolean oldPretty = outputContext.getPretty();
            outputContext.setPretty(false);
            if (textRep instanceof CDATASection) {
                outputContext.writeString("<![CDATA[");
                outputContext.writeString(textRep.getData());
                outputContext.writeString("]]>");
            } else if (textRep instanceof Comment) {
                outputContext.writeString("<!--");
                outputContext.writeString(textRep.getData());
                outputContext.writeString("-->");
            } else if (textRep instanceof Text) {
                outputContext.writeSafeString(textRep.getData());
            }
            outputContext.setPretty(oldPretty);
            return;
        }

        if (prefix != null)
            outputContext.registerPrefixForURI(prefix, namespaceURI);

        if (namespaces != null) {
            for (Iterator i = namespaces.iterator(); i.hasNext();) {
                Mapping mapping = (Mapping) i.next();
                outputContext.registerPrefixForURI(mapping.getPrefix(), mapping.getNamespaceURI());
            }
        }

        if (objectValue != null) {
            outputContext.serialize(new QName(namespaceURI, name),
                              attributes,
                              objectValue);
            return;
        }

        outputContext.startElement(new QName(namespaceURI, name), attributes);
        if (children != null) {
            for (Iterator it = children.iterator(); it.hasNext();) {
                ((NodeImpl)it.next()).output(outputContext);
            }
        }
        outputContext.endElement();
    }

    /**
     * Generate a string representation by serializing our contents
     * This is not a lightweight operation, and is repeated whenever
     * you call this method.
     * If the serialization fails, an error is logged and the classic
     * {@link Object#toString()} operation invoked instead.
     * @return a string representing the class
     */
    public String toString() {
        try {
            return getAsString();
        }
        catch( Exception exp ) {
            //couldn't turn to a string.
            //log it
            log.error(Messages.getMessage("exception00"), exp);
            //then hand off to our superclass, which is probably object
            return super.toString();
        }
    }

    /**
     * add a new namespace/prefix mapping
     * @param map new mapping to add
     * @todo: this code does not verify that the mapping does not exist already; it
     * is possible to create duplicate mappings.
     */
    public void addMapping(Mapping map) {
        if (namespaces == null) {
            namespaces = new ArrayList();
        }
        namespaces.add(map);
    }

    // JAXM SOAPElement methods...

    /**
     * add the child element
     * @param childName uri, prefix and local name of the element to add
     * @return the child element
     * @throws SOAPException
     * @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.Name)
     */
    public SOAPElement addChildElement(Name childName) throws SOAPException {
        MessageElement child = new MessageElement(childName.getLocalName(),
                                                  childName.getPrefix(),
                                                  childName.getURI());
        addChild(child);
        return child;
    }

    /**
     * add a child element in the message element's own namespace
     * @param localName
     * @return the child element
     * @throws SOAPException
     * @see javax.xml.soap.SOAPElement#addChildElement(String)
     */
    public SOAPElement addChildElement(String localName) throws SOAPException {
        // Inherit parent's namespace
        MessageElement child = new MessageElement(getNamespaceURI(),
                                                  localName);
        addChild(child);
        return child;
    }

    /**
     * add a child element
     * @param localName
     * @param prefixName
     * @return the child element
     * @throws SOAPException
     * @see javax.xml.soap.SOAPElement#addChildElement(String, String)
     */
    public SOAPElement addChildElement(String localName,
                                       String prefixName) throws SOAPException {
        MessageElement child = new MessageElement(getNamespaceURI(prefixName),
                                                  localName);
        child.setPrefix(prefixName);
        addChild(child);
        return child;
    }

    /**
     * add a child element
     * @param localName
     * @param childPrefix
     * @param uri
     * @return the child element
     * @throws SOAPException
     * @see javax.xml.soap.SOAPElement#addChildElement(String, String, String)
     */
    public SOAPElement addChildElement(String localName,
                                       String childPrefix,
                                       String uri) throws SOAPException {
        MessageElement child = new MessageElement(uri, localName);
        child.setPrefix(childPrefix);
        child.addNamespaceDeclaration(childPrefix, uri);
        addChild(child);
        return child;
    }

    /**
     * The added child must be an instance of MessageElement rather than
     * an abitrary SOAPElement otherwise a (wrapped) ClassCastException
     * will be thrown.
     * @see javax.xml.soap.SOAPElement#addChildElement(javax.xml.soap.SOAPElement)
     */
    public SOAPElement addChildElement(SOAPElement element)
        throws SOAPException {
        try {
            addChild((MessageElement)element);
            setDirty(true);
            return element;
        } catch (ClassCastException e) {
            throw new SOAPException(e);
        }
    }

    /**
     * add a text node to the document.
     * @return ourselves
     * @see javax.xml.soap.SOAPElement#addTextNode(String)
     */
    public SOAPElement addTextNode(String s) throws SOAPException {
        try {
            Text text = getOwnerDocument().createTextNode(s);
            ((org.apache.axis.message.Text)text).setParentElement(this);
            return this;
        } catch (java.lang.IncompatibleClassChangeError e) {
            Text text = new org.apache.axis.message.Text(s);
            this.appendChild(text);
            return this;
        } catch (ClassCastException e) {
            throw new SOAPException(e);
        }
    }

    /**
     * add a new attribute
     * @param attrName name of the attribute
     * @param value a string value
     * @return ourselves
     * @throws SOAPException
     * @see javax.xml.soap.SOAPElement#addAttribute(javax.xml.soap.Name, String)
     */
    public SOAPElement addAttribute(Name attrName, String value)
        throws SOAPException {
        try {
            addAttribute(attrName.getPrefix(), attrName.getURI(), attrName.getLocalName(), value);
        } catch (RuntimeException t) {
            throw new SOAPException(t);
        }
        return this;
    }

    /**
     * create a {@link Mapping} mapping and add to our namespace list.
     * @param prefix
     * @param uri
     * @return
     * @throws SOAPException for any {@link RuntimeException} caught
     * @todo for some reason this logic catches all rutime exceptions and
     * rethrows them as SOAPExceptions. This is unusual behavio, and should
     * be looked at closely.
     * @see javax.xml.soap.SOAPElement#addNamespaceDeclaration(String, String)
     */
    public SOAPElement addNamespaceDeclaration(String prefix,
                                               String uri)
        throws SOAPException {
        try {
            Mapping map = new Mapping(uri, prefix);
            addMapping(map);
        } catch (RuntimeException t) {
            //TODO: why is this here? Nowhere else do we turn runtimes into SOAPExceptions.
            throw new SOAPException(t);
        }
        return this;
    }

    /**
     * Get the value of an attribute whose namespace and local name are described.
     * @param attrName qualified name of the attribute
     * @return the attribute or null if there was no match
     * @see SOAPElement#getAttributeValue(javax.xml.soap.Name)
     */
    public String getAttributeValue(Name attrName) {
        return attributes.getValue(attrName.getURI(), attrName.getLocalName());
    }

    /**
     * Get an interator to all the attributes of the node.
     * The iterator is over a static snapshot of the node names; if attributes
     * are added or deleted during the iteration, this iterator will be not
     * be updated to follow the changes.
     * @return an iterator of the attributes.
     * @see javax.xml.soap.SOAPElement#getAllAttributes()
     */
    public Iterator getAllAttributes() {
        int num = attributes.getLength();
        Vector attrs = new Vector(num);
        for (int i = 0; i < num; i++) {
            String q = attributes.getQName(i);
            String prefix = "";
            if (q != null) {
                int idx = q.indexOf(":");
                if (idx > 0) {
                    prefix = q.substring(0, idx);
                } else {
                    prefix= "";
                }
            }

            attrs.add(new PrefixedQName(attributes.getURI(i),
                                        attributes.getLocalName(i),
                                        prefix));
        }
        return attrs.iterator();
    }

    // getNamespaceURI implemented above

    /**
     * get an iterator of the prefixes. The iterator
     * does not get updated in response to changes in the namespace list.
     * @return an iterator over a vector of prefixes
     * @see javax.xml.soap.SOAPElement#getNamespacePrefixes()
     */
    public Iterator getNamespacePrefixes() {
        Vector prefixes = new Vector();
        for (int i = 0; namespaces != null && i < namespaces.size(); i++) {
            prefixes.add(((Mapping)namespaces.get(i)).getPrefix());
        }
        return prefixes.iterator();
    }

    /**
     * get the full name of the element
     * @return
     * @see javax.xml.soap.SOAPElement#getElementName()
     */
    public Name getElementName() {
        return new PrefixedQName(getNamespaceURI(), getName(), getPrefix());
    }

    /**
     * remove an element
     * @param attrName name of the element
     * @return true if the attribute was found and removed.
     * @see javax.xml.soap.SOAPElement#removeAttribute(javax.xml.soap.Name)
     */
    public boolean removeAttribute(Name attrName) {
        AttributesImpl attributes = makeAttributesEditable();
        boolean removed = false;

        for (int i = 0; i < attributes.getLength() && !removed; i++) {
            if (attributes.getURI(i).equals(attrName.getURI()) &&
                attributes.getLocalName(i).equals(attrName.getLocalName())) {
                attributes.removeAttribute(i);
                removed = true;
            }
        }
        return removed;
    }

    /**
     * remove a namespace declaration.
     * @param namespacePrefix
     * @return true if the prefix was found and removed.
     * @see javax.xml.soap.SOAPElement#removeNamespaceDeclaration(String)
     */
    public boolean removeNamespaceDeclaration(String namespacePrefix) {
        makeAttributesEditable();
        boolean removed = false;

        for (int i = 0; namespaces != null && i < namespaces.size() && !removed; i++) {
            if (((Mapping)namespaces.get(i)).getPrefix().equals(namespacePrefix)) {
                namespaces.remove(i);
                removed = true;
            }
        }
        return removed;
    }

    /**
     * get an iterator over the children
     * This iterator <i>may</i> get confused if changes are made to the
     * children while the iteration is in progress.
     * @return an iterator over child elements.
     * @see javax.xml.soap.SOAPElement#getChildElements()
     */
    public Iterator getChildElements() {
        initializeChildren();
        return children.iterator();
    }

    /**
     * Convenience method to get the first matching child for a given QName.
     *
     * @param qname
     * @return child element or null
     * @see javax.xml.soap.SOAPElement#getChildElements()
     */
    public MessageElement getChildElement(QName qname) {
        if (children != null) {
            for (Iterator i = children.iterator(); i.hasNext();) {
                MessageElement child = (MessageElement) i.next();
                if (child.getQName().equals(qname))
                    return child;
            }
        }
        return null;
    }

    /**
     * get an iterator over child elements
     * @param qname namespace/element name of parts to find.
     * This iterator is not (currently) susceptible to change in the element
     * list during its lifetime, though changes in the contents of the elements
     * are picked up.
     * @return an iterator.
     */
    public Iterator getChildElements(QName qname) {
        initializeChildren();
        int num = children.size();
        Vector c = new Vector(num);
        for (int i = 0; i < num; i++) {
            MessageElement child = (MessageElement)children.get(i);
            Name cname = child.getElementName();
            if (cname.getURI().equals(qname.getNamespaceURI()) &&
                cname.getLocalName().equals(qname.getLocalPart())) {
                c.add(child);
            }
        }
        return c.iterator();
    }

    /**
     * get an iterator over child elements
     * @param childName namespace/element name of parts to find.
     * This iterator is not (currently) susceptible to change in the element
     * list during its lifetime, though changes in the contents of the elements
     * are picked up.
     * @return an iterator.
     * @see javax.xml.soap.SOAPElement#getChildElements(javax.xml.soap.Name)
     */
    public Iterator getChildElements(Name childName) {
        return getChildElements(new QName(childName.getURI(), childName.getLocalName()));
    }

    //DOM methods

    /**
     * @see org.w3c.dom.Element#getTagName()
     * @return the name of the element
     */
    public String getTagName() {
        return prefix == null ? name : prefix + ":" + name;
    }

    /**
     * remove a named attribute.
     * @see org.w3c.dom.Element#removeAttribute(String)
     * @param attrName name of the attributes
     * @throws DOMException
     */
    public void removeAttribute(String attrName) throws DOMException {
        AttributesImpl impl =  (AttributesImpl)attributes;
        int index = impl.getIndex(attrName);
        if(index >= 0){
            AttributesImpl newAttrs = new AttributesImpl();
            // copy except the removed attribute
            for(int i = 0; i < impl.getLength(); i++){ // shift after removal
                if(i != index){
                    String uri = impl.getURI(i);
                    String local = impl.getLocalName(i);
                    String qname = impl.getQName(i);
                    String type = impl.getType(i);
                    String value = impl.getValue(i);
                    newAttrs.addAttribute(uri,local,qname,type,value);
                }
            }
            // replace it
            attributes = newAttrs;
        }
    }

    /**
     * test for an attribute existing
     * @param attrName name of attribute (or null)
     * @return true if it exists
     * Note that the behaviour for a null parameter (returns false) is not guaranteed in future
     * @see org.w3c.dom.Element#hasAttribute(String)
     */
    public boolean hasAttribute(String attrName) {
        if(attrName == null)  // Do I have to send an exception?
            attrName = "";

        for(int i = 0; i < attributes.getLength(); i++){
            if(attrName.equals(attributes.getQName(i)))
                return true;
        }
        return false;
    }

    /**
     * get an attribute by name
     * @param attrName of attribute
     * @return the attribute value or null
     * @see org.w3c.dom.Element#getAttribute(String)
     */
    public String getAttribute(String attrName) {
        return attributes.getValue(attrName);
    }

    /**
     * Remove an attribute. If the removed
     * attribute has a default value it is immediately replaced. The
     * replacing attribute has the same namespace URI and local name, as
     * well as the original prefix.
     * If there is no matching attribute, the operation is a no-op.
     * @see org.w3c.dom.Element#removeAttributeNS(String, String)
     * @param namespace namespace of attr
     * @param localName local name
     * @throws DOMException
     */
    public void removeAttributeNS(String namespace, String localName) throws DOMException {
        makeAttributesEditable();
        Name name =  new PrefixedQName(namespace, localName, null);
        removeAttribute(name);
    }

    /**
     * set or update an attribute.
     * @see org.w3c.dom.Element#setAttribute(String, String)
     * @param name attribute name
     * @param value attribute value
     * @throws DOMException
     */
    public void setAttribute(String name, String value) throws DOMException {
        AttributesImpl impl =  makeAttributesEditable();
        int index = impl.getIndex(name);
        if (index < 0) { // not found
            String uri = "";
            String localname = name;
            String qname = name;
            String type = "CDDATA";
            impl.addAttribute(uri, localname, qname, type, value);
        } else {         // found
            impl.setLocalName(index, value);
        }
    }

    /**
     * Test for an attribute
     * @see org.w3c.dom.Element#hasAttributeNS(String, String)
     * @param namespace
     * @param localName
     * @return
     */
    public boolean hasAttributeNS(String namespace, String localName) {
        if (namespace == null) {
            namespace = "";
        }
        if (localName == null)  // Do I have to send an exception? or just return false
        {
            localName = "";
        }

        for(int i = 0; i < attributes.getLength(); i++){
            if( namespace.equals(attributes.getURI(i))
                    && localName.equals(attributes.getLocalName(i)))
                return true;
        }
        return false;
    }

    /**
     * This unimplemented operation is meand to return an attribute as a node
     * @see org.w3c.dom.Element#getAttributeNode(String)
     * @param attrName
     * @return null, always.
     * @todo Fix this for SAAJ 1.2 Implementation. marked as deprecated to warn people
     * it is broken
     * @deprecated this is not implemented
     */
    public Attr getAttributeNode(String attrName) {
        return null;
    }

    /**
     * remove a an attribue
     * @param oldAttr
     * @return oldAttr
     * @throws DOMException
     */
    public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
        makeAttributesEditable();
        Name name =  new PrefixedQName(oldAttr.getNamespaceURI(), oldAttr.getLocalName(), oldAttr.getPrefix());
        removeAttribute(name);
        return oldAttr;
    }

    /**
     * set the attribute node.
     * @see org.w3c.dom.Element#setAttributeNode(org.w3c.dom.Attr)
     * @param newAttr
     * @return newAttr
     * @throws DOMException
     * @deprecated this is not implemented
     * @todo implement
     */
    public Attr setAttributeNode(Attr newAttr) throws DOMException {
        return newAttr;
    }

    /**
     * set an attribute as a node
     * @see org.w3c.dom.Element#setAttributeNodeNS(org.w3c.dom.Attr)
     * @todo implement properly.
     * @param newAttr
     * @return null
     * @throws DOMException
     */
    public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
        //attributes.
        AttributesImpl attributes = makeAttributesEditable();
        // how to convert to DOM ATTR
        attributes.addAttribute(newAttr.getNamespaceURI(),
                newAttr.getLocalName(),
                newAttr.getLocalName(),
                "CDATA",
                newAttr.getValue());
        return null;
    }

    /**
     * @see org.w3c.dom.Element#getElementsByTagName(String)
     * @param tagName tag to look for.
     * @return a list of elements
     */
    public NodeList getElementsByTagName(String tagName) {
        NodeListImpl nodelist = new NodeListImpl();
        for (int i = 0; children != null && i < children.size(); i++) {
            if (children.get(i) instanceof Node) {
                Node el = (Node)children.get(i);
                if (el.getLocalName() != null && el.getLocalName()
                                .equals(tagName))
                    nodelist.addNode(el);
                if (el instanceof Element) {
                    NodeList grandchildren =
                            ((Element)el).getElementsByTagName(tagName);
                    for (int j = 0; j < grandchildren.getLength(); j++) {
                        nodelist.addNode(grandchildren.item(j));
                    }
                }
            }
        }
        return nodelist;
    }
    
    /**
     * get the attribute with namespace/local name match.
     * @see org.w3c.dom.Element#getAttributeNS(String, String)
     * @param namespaceURI namespace
     * @param localName name
     * @return string value or null if not found
     * @todo: this could be refactored to use getAttributeValue()
     */
    public String getAttributeNS(String namespaceURI, String localName) {
    	if(namespaceURI == null) {
    		namespaceURI = "";
    	}
        for (int i = 0; i < attributes.getLength(); i++) {
            if (attributes.getURI(i).equals(namespaceURI) &&
                    attributes.getLocalName(i).equals(localName)) {
                return  attributes.getValue(i);
            }
        }
        return null;
    }

    /**
     * set an attribute or alter an existing one
     * @see org.w3c.dom.Element#setAttributeNS(String, String, String)
     * @param namespaceURI namepsace
     * @param qualifiedName qualified name of the attribue
     * @param value value
     * @throws DOMException
     */
    public void setAttributeNS(String namespaceURI, String qualifiedName,
                               String value)
        throws DOMException
    {
        AttributesImpl attributes = makeAttributesEditable();
        String localName =  qualifiedName.substring(qualifiedName.indexOf(":")+1, qualifiedName.length());

        if (namespaceURI == null) {
            namespaceURI = "intentionalNullURI";
        }
        attributes.addAttribute(namespaceURI,
                localName,
                qualifiedName,
                "CDATA",
                value);
    }

    /**
     * @see org.w3c.dom.Element#getAttributeNS(String, String)
     * @deprecated not implemented!
     * @param namespace namespace
     * @param localName local name
     * @return null
     */
    public Attr getAttributeNodeNS(String namespace, String localName) {
        return null;  //TODO: Fix this for SAAJ 1.2 Implementation
    }

    /**
     * @see org.w3c.dom.Element#getElementsByTagNameNS(String, String)
     * @param namespace namespace
     * @param localName local name of element
     * @return (potentially empty) list of elements that match the (namespace,localname) tuple
     */
    public NodeList getElementsByTagNameNS(String namespace,
                                           String localName)
    {
        return getElementsNS(this,namespace,localName);
    }

    /**
     * helper method for recusively getting the element that has namespace URI and localname
     * @param parentElement parent element
     * @param namespace namespace
     * @param localName local name of element
     * @return (potentially empty) list of elements that match the (namespace,localname) tuple
     */
    protected NodeList getElementsNS(org.w3c.dom.Element parentElement,
                                     String namespace, String localName)
    {
        NodeList children = parentElement.getChildNodes();
        NodeListImpl matches = new NodeListImpl();

        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i) instanceof Text) {
                continue;
            }
            Element child = (Element) children.item(i);
            if (namespace.equals(child.getNamespaceURI()) &&
                    localName.equals(child.getLocalName())) {
                matches.addNode(child);
            }
            // search the grand-children.
            matches.addNodeList(child.getElementsByTagNameNS(namespace,
                    localName));
        }
        return matches;
    }

    /**
     * get a child node
     * @param index index value
     * @return child or null for out of range value
     * @see org.w3c.dom.NodeList#item(int)
     */
    public Node item(int index) {
        if (children != null && children.size() > index) {
            return (Node) children.get(index);
        } else {
            return null;
        }
    }

    /**
     * The number of nodes in the list. The range of valid child node indices
     * is 0 to <code>length-1</code> inclusive.
     * @return number of children
     * @since SAAJ 1.2 : Nodelist Interface
     * @see org.w3c.dom.NodeList#getLength()
     */
    public int getLength()
    {
        return (children == null) ? 0 : children.size();
    }

    // setEncodingStyle implemented above

    // getEncodingStyle() implemented above

    protected MessageElement findElement(Vector vec, String namespace,
                               String localPart)
    {
        if (vec.isEmpty()) {
            return null;
        }

        QName qname = new QName(namespace, localPart);
        Enumeration e = vec.elements();
        MessageElement element;
        while (e.hasMoreElements()) {
            element = (MessageElement) e.nextElement();
            if (element.getQName().equals(qname)) {
                return element;
            }
        }

        return null;
    }

    /**
     * equality test. Does a string match of the two message elements,
     * so is fairly brute force.
     * @see #toString()
     * @param obj
     * @return
     */
    public boolean equals(Object obj)
    {
        if (obj == null || !(obj instanceof MessageElement)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!this.getLocalName().equals(((MessageElement) obj).getLocalName())) {
            return false;
        }
        return toString().equals(obj.toString());
    }

    /**
     * recursively copy.
     * Note that this does not reset many of our fields, and must be used with caution.
     * @param element
     */
    private void copyNode(org.w3c.dom.Node element) {
        copyNode(this, element);
    }

    /**
     * recursive copy
     * @param dest element to copy into
     * @param source child element
     */
    private void copyNode(MessageElement dest, org.w3c.dom.Node source)
    {
        dest.setPrefix(source.getPrefix());
        if(source.getLocalName() != null) {
            dest.setQName(new QName(source.getNamespaceURI(), source.getLocalName()));
        }
        else
        {
            dest.setQName(new QName(source.getNamespaceURI(), source.getNodeName()));
        }

        NamedNodeMap attrs = source.getAttributes();
        for(int i = 0; i < attrs.getLength(); i++){
            Node att = attrs.item(i);
        if (att.getNamespaceURI() != null &&
                att.getPrefix() != null &&
                att.getNamespaceURI().equals(Constants.NS_URI_XMLNS) &&
                "xmlns".equals(att.getPrefix())) {
                Mapping map = new Mapping(att.getNodeValue(), att.getLocalName());
                dest.addMapping(map);
            }
            if(att.getLocalName() != null) {
                dest.addAttribute(att.getPrefix(),
                        (att.getNamespaceURI() != null ? att.getNamespaceURI() : ""),
                        att.getLocalName(),
                        att.getNodeValue());
            } else if (att.getNodeName() != null) {
                dest.addAttribute(att.getPrefix(),
                        (att.getNamespaceURI() != null ? att.getNamespaceURI() : ""),
                        att.getNodeName(),
                        att.getNodeValue());
            }
        }

        NodeList children = source.getChildNodes();
        for(int i = 0; i < children.getLength(); i++){
            Node child = children.item(i);
            if(child.getNodeType()==TEXT_NODE ||
               child.getNodeType()==CDATA_SECTION_NODE ||
               child.getNodeType()==COMMENT_NODE ) {
                org.apache.axis.message.Text childElement = 
                    new org.apache.axis.message.Text((CharacterData)child);
                dest.appendChild(childElement);
            } else {
                MessageElement childElement = new MessageElement();
                dest.appendChild(childElement);
                copyNode(childElement, child);
            }
        }
    }

    /**
     * Get the value of the doc as a string.
     * This uses {@link #getAsDOM()} so is a heavyweight operation.
     * @return the value of any child node, or null if there is no node/something went
     * wrong during serialization. If the first child is text, the return value
     * is the text itself.
     * @see javax.xml.soap.Node#getValue() ;
     */
    public String getValue() {
        /*--- Fix for AXIS-1817
        if ((recorder != null) && (!_isDirty)) {
            StringWriter writer = new StringWriter();
            TextSerializationContext outputContext = 
                new TextSerializationContext(writer);
            try {
                recorder.replay(startEventIndex,
                                endEventIndex,
                                new SAXOutputter(outputContext));
            } catch (Exception t) {
                log.debug("getValue()", t);
                return null;
            }
            String value = writer.toString();
            return (value.length() == 0) ? null : value;
        } 
        ---*/

        if (textRep != null) {
            // weird case: error?
            return textRep.getNodeValue();
        }

        if (objectValue != null) {
            return getValueDOM();
        }

        for (Iterator i = getChildElements(); i.hasNext(); ) {
            NodeImpl n = (NodeImpl) i.next();
            if (n instanceof Text) {
                return ((Text)n).getNodeValue();
            }
        }

        return null;
    }

    protected String getValueDOM() {
        try {
            Element element = getAsDOM();
            if (element.hasChildNodes()) {
                Node node = element.getFirstChild();
                if (node.getNodeType() == Node.TEXT_NODE) {
                    return node.getNodeValue();
                }
            }
        } catch (Exception t) {
            log.debug("getValue()", t);
        }
        return null;
    }

    public void setValue( String value )
    {
        // if possible, get objectValue in sync with Node value
        if (children==null) {
            try {
                setObjectValue(value);
            } catch ( SOAPException soape ) {
                log.debug("setValue()", soape);
            }
        }
        super.setValue(value);
    }

    public Document getOwnerDocument() {
        Document doc = null;
        if (context != null && context.getEnvelope() != null &&
                context.getEnvelope().getOwnerDocument() != null) {
            doc = context.getEnvelope().getOwnerDocument();
        }
        if(doc == null) {
            doc = super.getOwnerDocument();
        }
        if (doc == null) {
            doc = new SOAPDocumentImpl(null);
        }
        return doc;
    }
}
