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

import junit.framework.TestCase;
import org.apache.axiom.om.impl.dom.NodeImpl;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.Text;
import java.util.Iterator;
import java.util.List;

public class SOAPElementTest extends TestCase {

    private SOAPElement soapEle;

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

    public void testAddTextNode() {
        assertNotNull(soapEle);
        String value = "foo";
        try {
            soapEle.addTextNode(value);
        } catch (SOAPException e) {
            fail("Unexpected Exception " + e);
        }
        assertEquals(value, soapEle.getValue());
        TextImplEx text = assertContainsText(soapEle);
        assertEquals(value, text.getValue());
    }

    public void testChildren() {
        try {
            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);
        } catch (SOAPException e) {
            fail("Unexpected Exception " + e);
        }

        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).getNodeValue(),
                     ((javax.xml.soap.Text) z2).getNodeValue());

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

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

    public void testChildrenAndSiblings() {
        try {
            soapEle.addTextNode("foo");
            soapEle.addChildElement("Child1", "ch", "http://test.apache.org/");
            soapEle.addChildElement("Child2", "ch", "http://test.apache.org/");
        } catch (SOAPException e) {
            fail("Unexpected Exception " + e);
        }

        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).getNodeValue(),
                     ((javax.xml.soap.Text) z2).getNodeValue());

        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());
    }

    public void testCommentSibling() {
        try {
            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/");
        } catch (SOAPException e) {
            fail("Unexpected Exception " + e);
        }

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

    public void testCommentSibling2() {
        try {
            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/");
        } catch (SOAPException e) {
            fail("Unexpected Exception " + e);
        }

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

    public void testAddChildElement() {
        try {
            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");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            fail("Exception: " + e);
        }
    }

    public void testAddChildElement2() {
        try {
            SOAPMessage msg = MessageFactory.newInstance().createMessage();
            Name name = msg.getSOAPPart().getEnvelope().createName("MyName1", "MyPrefix1", "MyUri1");
            SOAPElement myse = SOAPFactory.newInstance().createElement(name);
            SOAPBody body = msg.getSOAPBody();
            SOAPElement se = body.addChildElement(myse);
            if (se == null) {
                fail("addChildElement() did not return SOAPElement");
            } else {
                Iterator i = body.getChildElements(name);
                int count = getIteratorCount(i);
                i = body.getChildElements(name);
                if (count != 1) {
                    fail("Wrong iterator count returned of " + count + ", expected 1");
                } else {
                    SOAPElement se2 = (SOAPElement) i.next();
                    if (!se.equals(se2)) {
                        fail();
                    }
                }
                Name n = se.getElementName();
                if (!n.equals(name)) {
                    fail("addChildElement() did not return " +
                         "correct name object expected localname=" +
                         name.getLocalName() + ", got localname="
                         + n.getLocalName());
                }
            }
        } catch (Exception e) {
            fail("Exception: " + e);
        }
    }

    public void testAddTextNode2() {
        try {
            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");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            fail("Exception: " + e);
        }
    }

    public void testRemoveAttribute() {
        try {
            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));
        } catch (Exception e) {
            e.printStackTrace();
            fail("Exception: " + e);
        }
    }

    public void testRemoveNamespaceDeclaration() {
        try {
            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));
        } catch (Exception e) {
            fail("Exception: " + e);
        }
    }

    public void testSetEncodingStyle(){
         try {
            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);
            }
        } catch (Exception e) {
            fail("Exception: " + e);
        }
    }

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

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

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