/*
 * 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 junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.Text;
import java.util.Iterator;
import java.util.List;

@RunWith(SAAJTestRunner.class)
public class SOAPElementTest extends Assert {

    private SOAPElement soapEle;

    @Before
    public void setUp() throws Exception {
        soapEle =
                SOAPFactoryImpl.newInstance().createElement("Test",
                                                            "test",
                                                            "http://test.apache.org/");
    }

    @Validated @Test
    public void testAddTextNode() throws Exception {
        assertNotNull(soapEle);
        String value = "foo";
        soapEle.addTextNode(value);
        assertEquals(value, soapEle.getValue());
        Text text = assertContainsText(soapEle);
        assertEquals(value, text.getValue());
    }

    @Validated @Test
    public void testChildren() throws Exception {
        soapEle.addTextNode("foo");
        SOAPElement childEle1 =
                SOAPFactoryImpl.newInstance().createElement("Child1",
                                                            "ch",
                                                            "http://test.apache.org/");
        SOAPElement childEle2 =
                SOAPFactoryImpl.newInstance().createElement("Child2",
                                                            "ch",
                                                            "http://test.apache.org/");
        soapEle.addChildElement(childEle1);
        soapEle.addChildElement(childEle2);

        Object o = soapEle.getChildElements().next();
        Object o2 = soapEle.getChildElements().next();

        assertSame(o, o2); // both elements should be the same SAAJ Node
        assertEquals(((javax.xml.soap.Text)o).getValue(),
                     ((javax.xml.soap.Text)o2).getValue());

        int childrenCount = 0;
        for (Iterator iter = soapEle.getChildElements(); iter.hasNext();) {
            iter.next();
            childrenCount ++;
        }
        assertEquals(3, childrenCount);

        Object z1 = soapEle.getChildNodes().item(0);
        Object z2 = soapEle.getFirstChild();

        assertSame(o, z1);   // should be same SAAJ Node
        assertSame(z1, z2);  // should be same SAAJ Node

        assertEquals(((javax.xml.soap.Text)z1).getValue(),
                     ((javax.xml.soap.Text)z2).getValue());

        Node lastChildNode = (Node)soapEle.getLastChild();
        SOAPElement lastChildSOAPEle = (SOAPElement)lastChildNode;

        assertEquals("Child2", lastChildSOAPEle.getLocalName());
        assertEquals("http://test.apache.org/", lastChildSOAPEle.getNamespaceURI());
        assertEquals("ch", lastChildSOAPEle.getPrefix());
    }

    @Validated @Test
    public void testChildrenAndSiblings() throws Exception {
        soapEle.addTextNode("foo");
        soapEle.addChildElement("Child1", "ch", "http://test.apache.org/");
        soapEle.addChildElement("Child2", "ch", "http://test.apache.org/");

        Object o = soapEle.getChildElements().next();
        Object o2 = soapEle.getChildElements().next();
        assertSame(o, o2); // both elements should be the same SAAJ Node
        assertEquals(((javax.xml.soap.Text)o).getValue(),
                     ((javax.xml.soap.Text)o2).getValue());

        int childrenCount = 0;
        for (Iterator iter = soapEle.getChildElements(); iter.hasNext();) {
            iter.next();
            childrenCount ++;
        }
        assertEquals(3, childrenCount);

        Object z1 = soapEle.getChildNodes().item(0);
        Object z2 = soapEle.getFirstChild();
        assertSame(o, z1);   // should be same SAAJ Node
        assertSame(z1, z2);  // should be same SAAJ Node
        assertEquals(((javax.xml.soap.Text)z1).getValue(),
                     ((javax.xml.soap.Text)z2).getValue());

        SOAPElement lastChildSOAPEle = (SOAPElement)soapEle.getLastChild();

        assertEquals("Child2", lastChildSOAPEle.getLocalName());
        assertEquals("ch:Child2", lastChildSOAPEle.getNodeName());
        assertEquals("http://test.apache.org/", lastChildSOAPEle.getNamespaceURI());
        assertEquals("ch", lastChildSOAPEle.getPrefix());
        assertNotNull(lastChildSOAPEle.getParentNode());
        assertTrue(lastChildSOAPEle.getPreviousSibling() instanceof javax.xml.soap.SOAPElement);
        assertNull(lastChildSOAPEle.getNextSibling());

        javax.xml.soap.Node firstChild = (javax.xml.soap.Node)soapEle.getFirstChild();
        javax.xml.soap.Node nextSibling = (javax.xml.soap.Node)(firstChild.getNextSibling());
        assertNull(firstChild.getPreviousSibling());

        assertTrue(firstChild instanceof javax.xml.soap.Text);
        assertTrue(nextSibling instanceof javax.xml.soap.SOAPElement);
        assertTrue(nextSibling.getPreviousSibling() instanceof javax.xml.soap.Text);
        assertEquals("Child1", nextSibling.getLocalName());
        assertEquals("ch:Child1", nextSibling.getNodeName());
        assertEquals("http://test.apache.org/", nextSibling.getNamespaceURI());
        assertEquals("ch", nextSibling.getPrefix());

        javax.xml.soap.Node nextSibling2 = (javax.xml.soap.Node)nextSibling.getNextSibling();
        assertEquals("Child2", nextSibling2.getLocalName());
        assertEquals("ch:Child2", nextSibling2.getNodeName());
        assertEquals("http://test.apache.org/", lastChildSOAPEle.getNamespaceURI());
        assertEquals("ch", nextSibling2.getPrefix());
        assertNull(nextSibling2.getNextSibling());
    }

    @Validated @Test
    public void testCommentSibling() throws Exception {
        soapEle.addTextNode("foo");
        soapEle.addChildElement("Child1", "ch", "http://test.apache.org/");
        soapEle.addTextNode("<!-- This is a Comment-->");
        soapEle.addChildElement("Child2", "ch", "http://test.apache.org/");

        assertTrue(((Text)soapEle.getFirstChild().getNextSibling().getNextSibling()).isComment());
        assertTrue(((Text)soapEle.getLastChild().getPreviousSibling()).isComment());
    }

    @Validated @Test
    public void testCommentSibling2() throws Exception {
        soapEle.addTextNode("foo");
        soapEle.addTextNode("<!-- This is a Comment-->");
        soapEle.addTextNode("bar");
        soapEle.addChildElement("Child1", "ch", "http://test.apache.org/");
        soapEle.addChildElement("Child2", "ch", "http://test.apache.org/");

        assertTrue(((Text)soapEle.getFirstChild().getNextSibling()).isComment());
        assertFalse(((Text)soapEle.getLastChild().getPreviousSibling()
                .getPreviousSibling()).isComment());
        assertFalse(((Text)soapEle.getLastChild().getPreviousSibling()
                .getPreviousSibling()).isComment());
    }

    @Validated @Test
    public void testAddChildElementWithUndeclaredNamespace() throws Exception {
        SOAPElement element = SOAPFactory.newInstance().createElement("test");
        SOAPElement child = element.addChildElement("test", "p", "urn:ns");
        assertEquals(0, element.getAttributes().getLength());
        assertEquals("urn:ns", child.getNamespaceURI());
        assertEquals("p", child.getPrefix());
        assertEquals("test", child.getLocalName());
        Attr nsDecl = child.getAttributeNodeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "p");
        assertNotNull(nsDecl);
        assertEquals("urn:ns", nsDecl.getValue());
    }
    
    @Validated @Test
    public void testAddChildElementWithDeclaredNamespace() throws Exception {
        SOAPElement element = SOAPFactory.newInstance().createElement("test");
        element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:p", "urn:ns");
        SOAPElement child = element.addChildElement("test", "p", "urn:ns");
        assertEquals("urn:ns", child.getNamespaceURI());
        assertEquals("p", child.getPrefix());
        assertEquals("test", child.getLocalName());
        // TODO: don't know how to fix this :-(
//        assertEquals(0, child.getAttributes().getLength());
    }
    
    @Validated @Test
    public void testAddChildElement() throws Exception {
        String s = "MyName1";
        String p = "MyPrefix1";
        String u = "myURI";
        SOAPBody body = MessageFactory.newInstance().createMessage().getSOAPBody();
        SOAPElement myse = body.addNamespaceDeclaration(p, u);
        SOAPElement se = body.addChildElement(s, p);
        if (se == null) {
            fail("SOAPElement was null");
        } else {
            Iterator i = body.getChildElements();
            int count = getIteratorCount(i);
            i = body.getChildElements();
            if (count != 1) {
                fail("Wrong iterator count returned of " + count + ", expected 1");
            } else {
                SOAPElement se2 = (SOAPElement)i.next();
                if (!se.equals(se2)) {
                    fail("Elements not equal");
                }
            }
            String name = se.getElementName().getLocalName();
            Name n = se.getElementName();
            String prefix = se.getElementName().getPrefix();
            if (!name.equals(s) || !prefix.equals(p)) {
                fail("addChildElement() did not return correct local name and prefix");
            }
        }
    }

    @Validated @Test
    public void testAddChildElement2() throws Exception {
        boolean pass = true;
        SOAPMessage msg =
                MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
        SOAPEnvelope soapEnvelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = msg.getSOAPBody();

        Name name = soapEnvelope.createName("MyChild1");
        //Add child element Name object with localName=MyChild1
        SOAPElement se = body.addChildElement(name);
        if (se == null) {
            fail("addChildElement() did not return SOAPElement");
            //pass = false;
        } else {
            //Find the child element just added
            Iterator childs = body.getChildElements(name);
            int count = 0;
            while (childs.hasNext()) {
                Object obj = (Object)childs.next();
                count++;
            }

            childs = body.getChildElements(name);
            assertTrue(count == 1);

            SOAPElement se2 = (SOAPElement)childs.next();
            assertEquals(se, se2);
            //se = se2 (expected)

            //Retrieve the SOAPElement Name
            Name n = se.getElementName();
            //System.out.println("localName="+n.getLocalName()+" prefix="
            //			+n.getPrefix()+" URI="+n.getURI()+" qualifiedName="
            //			+n.getQualifiedName());
            assertEquals(n, name);
            //if (!n.equals(name)) {
            //System.out.println("Name objects are not equal (unexpected)");
            //System.out.println("addChildElement() did not return " +
            //"correct Name object expected localName=" +
            //name.getLocalName() + ", got localName="
            //+ n.getLocalName());
            //}

            //Name objects are equal (expected)
        }
    }

    @Validated @Test
    public void testAddTextNode2() throws Exception {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        Iterator iStart = envelope.getChildElements();
        int countStart = getIteratorCount(iStart);
        SOAPElement se = envelope.addTextNode("<txt>This is text</txt>");
        if (se == null) {
            fail("addTextNode() did not return SOAPElement");
        } else if (!envelope.getValue().equals("<txt>This is text</txt>")) {
            String s = body.getValue();
            fail("addTextNode() did not return expected text, Returned " + s +
                    ", Expected <txt>This is text</txt>");
        }
        Iterator i = envelope.getChildElements();
        int count = getIteratorCount(i);
        i = envelope.getChildElements();
        if (count != ++countStart) {
            fail("Wrong iterator count returned of " +
                    count + ", expected " + countStart);
        } else {
            Object obj = null;
            while (i.hasNext()) {
                obj = i.next();
                if (obj instanceof Text) {
                    break;
                }
            }
            if (!(obj instanceof Text)) {
                fail("obj is not instanceof Text");
            }
        }
    }

    @Validated @Test
    public void testRemoveAttribute() throws Exception {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        Name name = envelope.createName("MyAttr1");
        String value = "MyValue1";
        body.addAttribute(name, value);
        boolean b = body.removeAttribute(name);
        assertTrue("removeAttribute() did not return true", b);
        b = body.removeAttribute(name);
        assertFalse("removeAttribute() did not return false", b);
        assertNull(body.getAttributeValue(name));
    }

    @Validated @Test
    public void testRemoveAttribute2() throws Exception {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();

        QName name = new QName("MyAttr1");
        String value = "MyValue1";
        body.addAttribute(name, value);
        boolean b = body.removeAttribute(name);
        assertTrue(b);

        b = body.removeAttribute(name);
        if (b) {
            //removeAttribute() did not return false
            fail();
        }
        //getAttributeValue should return null
        assertNull(body.getAttributeValue(name));
    }

    @Validated @Test
    public void testRemoveAttributeName() throws Exception {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();

        Name name = envelope.createName("MyAttr1");
        String value = "MyValue1";
        body.addAttribute(name, value);
        boolean b = body.removeAttribute(name);
        assertTrue(b);

        b = body.removeAttribute(name);
        assertTrue(!b);

        String s = body.getAttributeValue(name);
        assertNull(s);
    }


    public void _testRemoveAttributeQName() throws Exception {
        SOAPMessage msg =
                MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();

        QName name = new QName("MyAttr1");
        String value = "MyValue1";
        body.addAttribute(name, value);
        boolean b = body.removeAttribute(name);
        assertTrue(b);
        b = body.removeAttribute(name);
        assertTrue(!b);

        assertNull(body.getAttributeValue(name));
    }

    @Validated @Test
    public void testAddNamespaceDeclarationDefaultNamespace() throws SOAPException {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        SOAPElement element = body.addChildElement("test", "p", "urn:test");
        element.addNamespaceDeclaration("", "urn:ns");
        Attr attr = (Attr)element.getAttributes().getNamedItemNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns");
        assertEquals("urn:ns", attr.getValue());
    }
    
    @Validated @Test
    public void testRemoveNamespaceDeclaration() throws Exception {
        String prefix = "myPrefix";
        String uri = "myURI";
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        body.addNamespaceDeclaration(prefix, uri);
        boolean b = body.removeNamespaceDeclaration(prefix);
        assertTrue("removeNamespaceDeclaration() did not return true", b);
        b = body.removeNamespaceDeclaration(prefix);
        assertFalse("removeNamespaceDeclaration() did not return false", b);
        assertNull(body.getNamespaceURI(prefix));
    }

    @Validated @Test
    public void testSetEncodingStyle() throws Exception {
        SOAPMessage msg = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        body.setEncodingStyle(SOAPConstants.URI_NS_SOAP_ENCODING);
        try {
            body.setEncodingStyle("BOGUS");
            fail("Expected Exception did not occur");
        } catch (IllegalArgumentException e) {
            assertTrue("Expected Exception occurred", true);
        }
    }

    private int getIteratorCount(Iterator iter) {
        int count = 0;
        while (iter.hasNext()) {
            iter.next();
            count ++;
        }
        return count;
    }

    private Text assertContainsText(SOAPElement soapElem) {
        assertTrue(soapElem.hasChildNodes());
        List childElems = toList(soapElem.getChildElements());
        assertTrue(childElems.size() == 1);
        Node node = (Node)childElems.get(0);
        assertTrue(node instanceof Text);
        return (Text)node;
    }

    private List toList(java.util.Iterator iter) {
        List list = new java.util.ArrayList();
        while (iter.hasNext()) {
            list.add(iter.next());
        }
        return list;
    }


    /*
    * test for addChildElement(QName qname)
    */
    @Validated @Test
    public void testAddChildElement3() throws Exception {
        QName qname = new QName("http://sample.apache.org/trader", "GetStockQuote", "w");
        soapEle.addChildElement(qname);
        assertNotNull(soapEle);
    }


    @Validated @Test
    public void testGetAttributeValue() throws Exception {
        assertNotNull(soapEle);
        String value = "234.50";
        QName qname = new QName("http://sample.apache.org/trader", "GetStockQuote", "w");
        soapEle.addAttribute(qname, value);
        String valueReturned = soapEle.getAttributeValue(qname);
        assertEquals(value, valueReturned);
    }


    public void _testGetChildElements() throws Exception {
        SOAPElement childEle1 =
                SOAPFactoryImpl.newInstance().createElement("Child1",
                                                            "ch",
                                                            "http://test.apache.org/");
        SOAPElement childEle2 =
                SOAPFactoryImpl.newInstance().createElement("Child2",
                                                            "ch",
                                                            "http://test.apache.org/");
        childEle1.addChildElement(childEle2);
        soapEle.addChildElement(childEle1);

        QName qname = new QName("http://test.apache.org/", "Child1", "ch");
        Iterator childElements = soapEle.getChildElements(qname);


        int childCount = 0;
        while (childElements.hasNext()) {
            Node node = (Node)childElements.next();
            childCount++;
        }
        assertEquals(childCount, 2);
    }

    @Validated @Test
    public void testGetChildElements2() throws Exception {
        MessageFactory fact = MessageFactory.newInstance();
        SOAPMessage message = fact.createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
        SOAPBody soapBody = soapEnvelope.getBody();

        Name name = soapEnvelope.createName("MyChild1");
        SOAPElement se = soapBody.addChildElement(name);
        Iterator childElementsCount = soapBody.getChildElements();
        Iterator childElements = soapBody.getChildElements();

        int childCount = 0;
        while (childElementsCount.hasNext()) {
            Node node = (Node)childElementsCount.next();
            childCount++;
        }
        assertEquals(childCount, 1);
        SOAPElement se2 = (SOAPElement)childElements.next();
        if (!se.equals(se2)) {
            fail();
        } else {
            System.out.println("SOAPElement se = se2 (expected)");
        }

        Name n = se.getElementName();
        assertEquals(n, name);
    }

    @Validated @Test
    public void testGetChildElements3() throws Exception {
        MessageFactory fact = MessageFactory.newInstance();
        SOAPMessage message = fact.createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
        SOAPBody soapBody = soapEnvelope.getBody();

        //Name name = soapEnvelope.createName("MyChild1");
        QName name = new QName("MyChild1");
        SOAPElement se = soapBody.addChildElement(name);
        Iterator childElementsCount = soapBody.getChildElements();
        Iterator childElements = soapBody.getChildElements();

        int childCount = 0;
        while (childElementsCount.hasNext()) {
            Node node = (Node)childElementsCount.next();
            childCount++;
        }
        assertEquals(childCount, 1);
        SOAPElement se2 = (SOAPElement)childElements.next();
        assertEquals(se, se2);

        QName n = se.getElementQName();
        assertEquals(n, name);
    }

    @Validated @Test
    public void testRemoveAttribute3() throws Exception {
        QName qname = new QName("http://child1.apache.org/", "Child1", "ch");
        String value = "MyValue1";
        soapEle.addAttribute(qname, value);
        boolean b = soapEle.removeAttribute(qname);
        assertTrue("removeAttribute() did not return true", b);
        b = soapEle.removeAttribute(qname);
        assertFalse("removeAttribute() did not return false", b);
        assertNull(soapEle.getAttributeValue(qname));
    }

    public void _testSetElementQName() throws Exception {
        QName qname = new QName("http://child1.apache.org/", "newName", "ch");
        soapEle.setElementQName(qname);
        assertNull(soapEle.getElementName().getLocalName(), "newName");
    }

    public void _testCreateQName() throws Exception {
        String prefix = "";
        //SOAPMessage message = MessageFactory.newInstance().createMessage();
        SOAPMessage message =
                MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        SOAPBody body = envelope.getBody();

        QName qname = envelope.createQName("qname", prefix);
        String tprefix = qname.getPrefix();
        String turi = qname.getNamespaceURI();
        String tname = qname.getLocalPart();
        if (!tprefix.equals(prefix) || !turi.equals(envelope.getElementName().getURI())) {
            fail("createQName() did not create correct qname\n" +
                    "expected: <uri=" + envelope.getElementName().getURI() +
                    ", prefix=" + prefix + ", localpart=qname>\n" +
                    "got:      <uri=" + turi +
                    ", prefix=" + tprefix + ", localpart=" + tname + ">");
        }
        qname = body.createQName("qname", body.getElementName().getPrefix());
        tprefix = qname.getPrefix();
        turi = qname.getNamespaceURI();
        tname = qname.getLocalPart();
        if (!tprefix.equals(body.getElementName().getPrefix()) ||
                !turi.equals(body.getElementName().getURI())) {
            fail("createQName() did not create correct qname\n" +
                    "expected: <uri=" + body.getElementName().getURI() +
                    ", prefix=" + body.getElementName().getPrefix() + ", localpart=qname>\n" +
                    "got:      <uri=" + turi +
                    ", prefix=" + tprefix + ", localpart=" + tname + ">");
        }
    }

    @Validated @Test(expected=SOAPException.class)
    public void testCreateQNameWithUnknownPrefix() throws Exception {
        soapEle.createQName("local", "nonexistingprefix");
    }

    @Validated @Test
    public void testCreateQNameWithAddNamespaceDeclaration() throws Exception {
        soapEle.addNamespaceDeclaration("p", "urn:test");
        QName qname = soapEle.createQName("local", "p");
        assertEquals("p", qname.getPrefix());
        assertEquals("local", qname.getLocalPart());
        assertEquals("urn:test", qname.getNamespaceURI());
    }

    @Validated @Test
    public void testRemoveContent() throws Exception {
        boolean pass = true;
        MessageFactory factory = MessageFactory.newInstance();
        SOAPMessage message = factory.createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        SOAPBody body = envelope.getBody();

        Name name = envelope.createName("MyChild");
        SOAPElement se = body.addChildElement(name);
        assertNotNull(se);
        Iterator childs = body.getChildElements(name);
        int childElementCount = 0;
        for (int a = 0; childs.hasNext(); a++) {
            childs.next();
            childElementCount++;
        }
        childs = body.getChildElements(name);
        assertEquals(childElementCount, 1);

        Name n = se.getElementName();
        assertEquals(n, name);
        //Child addition verified, now call removeContents to delete it
        se.removeContents();
        childs = se.getChildElements();
        childElementCount = 0;
        for (int a = 0; childs.hasNext(); a++) {
            childs.next();
            childElementCount++;
        }
        assertEquals(childElementCount, 0);
    }

    @Validated @Test
    public void testSetElementQName() throws Exception {
        MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        SOAPMessage message = factory.createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        SOAPBody body = envelope.getBody();

        QName qname1 = new QName("http://fooURI.com", "fooElement", "foo");
        QName qname2 = new QName("http://foo2URI.com", "fooElement2", "foo2");
        SOAPElement se = body.addChildElement(qname1);
        QName qname = se.getElementQName();
        se = se.setElementQName(qname2);
        qname = se.getElementQName();

        if (!qname.getNamespaceURI().equals(qname2.getNamespaceURI()) ||
                !qname.getLocalPart().equals(qname2.getLocalPart()) ||
                !qname.getPrefix().equals(qname2.getPrefix())) {
            System.out.println("setElementQName() did not reset " +
                    "element qname\nexpected: <URI=" + qname2.getNamespaceURI() +
                    ", prefix=" + qname2.getPrefix() + ", localpart=" + qname2.getLocalPart() +
                    ">\ngot:      <URI=" + qname.getNamespaceURI() + ", prefix=" +
                    qname.getPrefix() +
                    ", localpart=" + qname.getLocalPart() + ">");
        }
    }

    @Validated @Test
    public void testSetElementQName2() throws Exception {
        MessageFactory factory = MessageFactory.newInstance();
        SOAPMessage message = factory.createMessage();
        SOAPPart soapPart = message.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        SOAPBody body = envelope.getBody();
        SOAPHeader header = envelope.getHeader();

        QName qname = new QName("qname");
        //Try and change element name of SOAPEnvelope (expect SOAPException)
        try {
            envelope.setElementQName(qname);
            fail("Did not throw expected SOAPException");
        } catch (SOAPException e) {
            //Caught expected SOAPException
        }

        //Try and change element name of SOAPHeader (expect SOAPException)
        try {
            header.setElementQName(qname);
            fail("Did not throw expected SOAPException");
        } catch (SOAPException e) {
            //Caught expected SOAPException
        }

        //Try and change element name of SOAPBody (expect SOAPException)
        try {
            body.setElementQName(qname);
            fail("Did not throw expected SOAPException");
        } catch (SOAPException e) {
            //Caught expected SOAPException
        }
    }
    
    @Validated @Test
    public void testAppendChild() throws Exception {
        MessageFactory fact = MessageFactory.newInstance();
        SOAPMessage message = fact.createMessage();
        SOAPBody soapBody = message.getSOAPBody();

        QName qname1 = new QName("http://wombat.ztrade.com",
                                 "GetLastTradePrice", "ztrade");
        SOAPElement child = soapBody.addChildElement(qname1);
        
        assertFalse(child.getChildElements().hasNext());
        
        Document doc = child.getOwnerDocument();        
        String namespace = "http://example.com";
        String localName = "GetLastTradePrice";
        Element getLastTradePrice = doc.createElementNS(namespace, localName);        
        Element symbol = doc.createElement("symbol");
        symbol.setAttribute("foo", "bar");
        getLastTradePrice.appendChild(symbol);
        org.w3c.dom.Text def = doc.createTextNode("DEF");
        symbol.appendChild(def);
                
        child.appendChild(getLastTradePrice);
        
        Iterator iter = child.getChildElements();
        assertTrue(iter.hasNext()); 
        Object obj = iter.next();
        assertTrue(obj instanceof SOAPElement);  
        SOAPElement soapElement = (SOAPElement)obj;
        assertEquals(namespace, soapElement.getNamespaceURI());
        assertEquals(localName, soapElement.getLocalName());
        assertFalse(iter.hasNext());
        
        iter = soapElement.getChildElements();
        assertTrue(iter.hasNext()); 
        obj = iter.next();
        assertTrue(obj instanceof SOAPElement);  
        soapElement = (SOAPElement)obj;
        assertEquals(null, soapElement.getNamespaceURI());
        assertEquals("symbol", soapElement.getLocalName());
        assertFalse(iter.hasNext());
        
        iter = soapElement.getChildElements();
        assertTrue(iter.hasNext()); 
        obj = iter.next();
        assertTrue(obj instanceof Text);  
        Text text = (Text)obj;
        assertEquals("DEF", text.getData());
        assertFalse(iter.hasNext());               
    }
    
    @Validated @Test
    public void testRemoveChild() throws Exception {
        MessageFactory fact = MessageFactory.newInstance();
        SOAPMessage message = fact.createMessage();
        SOAPBody soapBody = message.getSOAPBody();

        assertFalse(soapBody.getChildElements().hasNext());
        
        QName qname1 = new QName("http://wombat.ztrade.com",
                                 "GetLastTradePrice", "ztrade");
        SOAPElement child = soapBody.addChildElement(qname1);
        child.addTextNode("foo");
        
        assertTrue(child.getChildElements().hasNext());
        
        Node textNode = (Node)child.getChildElements().next();
        assertTrue(textNode instanceof Text);
        
        /* 
        child.removeChild(textNode);
        
        assertFalse(child.getChildElements().hasNext());
        */
        
        assertTrue(soapBody.getChildElements().hasNext());
        
        soapBody.removeChild(child);
        
        assertFalse(soapBody.getChildElements().hasNext());
    }
    
    @Validated @Test
    public void testAddRemoveTextNode() throws Exception {
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage msg = mf.createMessage();
        SOAPBody body = msg.getSOAPBody();
        SOAPBodyElement bodyChild = body.addBodyElement(new QName("TestChild"));
        bodyChild.addTextNode("aaaaa");
        bodyChild.removeChild(bodyChild.getFirstChild());
    }
}
