/*
 * 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.schema.testsuite;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.StAXUtils;
import services.echo.types.*;

import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;

public class OuterElementsTest extends AbstractTest {

    public static final int NILLABLE_TRUE = 0;
    public static final int NILLABLE_FALSE = 1;

    public void testString() {
        String returnString;
        try {
            returnString = testString(null, NILLABLE_TRUE);
            assertEquals(returnString, null);
            returnString = testString("Test String", NILLABLE_TRUE);
            assertEquals(returnString, "Test String");
        } catch (Exception e) {
            fail();
        }

        try {
            returnString = testString(null, NILLABLE_FALSE);
            fail();
        } catch (Exception e) {
            assertTrue(true);
        }

        try {
            returnString = testString("Test String", NILLABLE_FALSE);
            assertEquals(returnString, "Test String");
        } catch (Exception e) {
            fail();
        }
    }

    private String testString(String innerElement, int type) throws Exception {
        OMElement omElement;
        String returnString = null;
        String omElementString;

        switch (type) {
            case NILLABLE_TRUE : {
                OuterTestString1 outerTestString = new OuterTestString1();
                outerTestString.setOuterTestString1(innerElement);
                omElement = outerTestString.getOMElement(OuterTestString1.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnString = OuterTestString1.Factory.parse(xmlReader).getOuterTestString1();
                break;
            }

            case NILLABLE_FALSE : {
                OuterTestString2 outerTestString = new OuterTestString2();
                outerTestString.setOuterTestString2(innerElement);
                omElement = outerTestString.getOMElement(OuterTestString2.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnString = OuterTestString2.Factory.parse(xmlReader).getOuterTestString2();
                break;

            }
        }
        return returnString;
    }

    public void testInt() {
        int returnInt;
        try {
            returnInt = testInt(5, NILLABLE_TRUE);
            assertEquals(returnInt, 5);
            returnInt = testInt(5, NILLABLE_FALSE);
            assertEquals(returnInt, 5);
        } catch (Exception e) {
            fail();
        }
    }

    private int testInt(int innerElement, int type) throws Exception {
        OMElement omElement;
        int returnInt = 0;
        String omElementString;
        switch (type) {
            case NILLABLE_TRUE : {
                OuterTestInt1 outerTestInt = new OuterTestInt1();
                outerTestInt.setOuterTestInt1(innerElement);
                omElement = outerTestInt.getOMElement(OuterTestInt1.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnInt = OuterTestInt1.Factory.parse(xmlReader).getOuterTestInt1();
                break;
            }
            case NILLABLE_FALSE : {
                OuterTestInt2 outerTestInt = new OuterTestInt2();
                outerTestInt.setOuterTestInt2(innerElement);
                omElement = outerTestInt.getOMElement(OuterTestInt2.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnInt = OuterTestInt2.Factory.parse(xmlReader).getOuterTestInt2();
                break;
            }
        }
        return returnInt;
    }

    public void testAnyType() {
        OMElement returnObject;
        try {
            returnObject = testAnyType(null, NILLABLE_TRUE);
            assertTrue(isOMElementsEqual(returnObject, null));
            returnObject = testAnyType(getOMElement(), NILLABLE_TRUE);
            assertTrue(isOMElementsEqual(returnObject, getOMElement()));
        } catch (Exception e) {
            fail();
        }

        try {
            returnObject = testAnyType(null, NILLABLE_FALSE);
            fail();
        } catch (Exception e) {
            assertTrue(true);
        }

        try {
            returnObject = testAnyType(getOMElement(), NILLABLE_FALSE);
            assertTrue(isOMElementsEqual(returnObject, getOMElement()));
        } catch (Exception e) {
            fail();
        }
    }

    private OMElement testAnyType(OMElement innerElement, int type) throws Exception {
        OMElement omElement;
        OMElement returnString = null;
        String omElementString;

        switch (type) {
            case NILLABLE_TRUE : {
                OuterTestAnyType1 outerTestAnyType = new OuterTestAnyType1();
                outerTestAnyType.setOuterTestAnyType1(innerElement);
                omElement = outerTestAnyType.getOMElement(OuterTestAnyType1.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnString = OuterTestAnyType1.Factory.parse(xmlReader).getOuterTestAnyType1();
                break;
            }

            case NILLABLE_FALSE : {
                OuterTestAnyType2 outerTestAnyType = new OuterTestAnyType2();
                outerTestAnyType.setOuterTestAnyType2(innerElement);
                omElement = outerTestAnyType.getOMElement(OuterTestAnyType2.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnString = OuterTestAnyType2.Factory.parse(xmlReader).getOuterTestAnyType2();
                break;
            }
        }
        return returnString;
    }

    public void testBookInformation() {
        BookInformation returnObject;
        try {
            returnObject = testBookInformation(null, NILLABLE_TRUE);
            assertTrue(isBookInformationObjectsEquals(returnObject, null));
            returnObject = testBookInformation(getBookInformation(), NILLABLE_TRUE);
            assertTrue(isBookInformationObjectsEquals(returnObject, getBookInformation()));
        } catch (Exception e) {
            fail();
        }

        try {
            returnObject = testBookInformation(null, NILLABLE_FALSE);
            fail();
        } catch (Exception e) {
            assertTrue(true);
        }

        try {
            returnObject = testBookInformation(getBookInformation(), NILLABLE_FALSE);
            assertTrue(isBookInformationObjectsEquals(returnObject, getBookInformation()));
        } catch (Exception e) {
            fail();
        }
    }

    private BookInformation testBookInformation(BookInformation innerElement, int type) throws Exception {
        OMElement omElement;
        BookInformation returnObject = null;
        String omElementString;

        switch (type) {
            case NILLABLE_TRUE : {
                OuterTestBookInformation1 outerTestBookInformation = new OuterTestBookInformation1();
                outerTestBookInformation.setOuterTestBookInformation1(innerElement);
                omElement = outerTestBookInformation.getOMElement(OuterTestBookInformation1.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnObject = OuterTestBookInformation1.Factory.parse(xmlReader).getOuterTestBookInformation1();
                break;
            }

            case NILLABLE_FALSE : {
                OuterTestBookInformation2 outerTestBookInformation = new OuterTestBookInformation2();
                outerTestBookInformation.setOuterTestBookInformation2(innerElement);
                omElement = outerTestBookInformation.getOMElement(OuterTestBookInformation2.MY_QNAME, OMAbstractFactory.getSOAP12Factory());
                omElementString = omElement.toStringWithConsume();
                System.out.println("OMElement ==> " + omElementString);
                XMLStreamReader xmlReader =
                        StAXUtils.createXMLStreamReader(new ByteArrayInputStream(omElementString.getBytes()));
                returnObject = OuterTestBookInformation2.Factory.parse(xmlReader).getOuterTestBookInformation2();
                break;
            }
        }
        return returnObject;
    }


}
