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

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.wsdl.xml.WSDLLocator;
import javax.xml.namespace.QName;

import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaObject;
import org.xml.sax.InputSource;

import junit.framework.TestCase;

public class WSDL11ToAxisServiceBuilderTest extends TestCase {
    /**
     * Tests processing of an operation that declares multiple faults referring to the same message.
     * In this case, {@link WSDL11ToAxisServiceBuilder} must correctly populate the
     * {@link AxisMessage} object for both faults. In particular,
     * {@link AxisMessage#getElementQName()} must return consistent information. This is a
     * regression test for AXIS2-4533.
     * 
     * @throws Exception
     */
    public void testMultipleFaultsWithSameMessage() throws Exception {
        InputStream in = new FileInputStream("test-resources/wsdl/faults.wsdl");
        try {
            AxisService service = new WSDL11ToAxisServiceBuilder(in).populateService();
            AxisOperation operation = service.getOperation(new QName("urn:test", "test"));
            assertNotNull(operation);
            List<AxisMessage> faultMessages = operation.getFaultMessages();
            assertEquals(2, faultMessages.size());
            AxisMessage error1 = faultMessages.get(0);
            AxisMessage error2 = faultMessages.get(1);
            assertEquals("errorMessage", error1.getName());
            assertEquals("errorMessage", error2.getName());
            assertEquals(new QName("urn:test", "error"), error1.getElementQName());
            assertEquals(new QName("urn:test", "error"), error2.getElementQName());
        } finally {
            in.close();
        }
    }
    
    public void testNonDuplicatedElementsHttpBinding() throws Exception {
        final String wsdlPath = "test-resources/wsdl/nonduplicatedElements.wsdl";
        InputStream in = new FileInputStream(wsdlPath);
        final String targetNamespace = "http://www.example.org";
        final QName serviceName = new QName(targetNamespace, "FooService");
        final String portName = "FooHttpGetPort";
          
        AxisService service = new WSDL11ToAxisServiceBuilder(in, serviceName, portName).populateService();
        List<XmlSchema> schemaDocuments = service.getSchema();
        List<QName> duplicatedGlobalElements = findDuplicatedGlobalElements(schemaDocuments);
        // NO duplicated element should exists
        assertTrue("Duplicated global element declarations found in '" +  wsdlPath, 
            duplicatedGlobalElements.isEmpty());
    }

    protected List<QName> findDuplicatedGlobalElements(List<XmlSchema> schemaDocuments) {
        List<QName> duplicatedGlobalElementDeclarations = new ArrayList<QName>();
        Set<QName> globalElementDeclarations = new HashSet<QName>();
        // Iterate over all schema documents
        for (XmlSchema schemaDocument : schemaDocuments) {
            for (XmlSchemaObject xmlSchemaObject : schemaDocument.getItems()) {
                // Check only XML schema elements
                if (xmlSchemaObject instanceof XmlSchemaElement) {
                    QName elementName = ((XmlSchemaElement)xmlSchemaObject).getQName();
                    /* Was another element with the same name found in this or
                      other XML schema document? */
                    if (globalElementDeclarations.contains(elementName)) {
                        duplicatedGlobalElementDeclarations.add(elementName);
                    } else {
                        globalElementDeclarations.add(elementName);
                    }
                }
            }
        }
        return duplicatedGlobalElementDeclarations;
    }

    private AxisService populateAxisService(AxisConfiguration axisConf, File wsdlFile) throws IOException {
        InputStream in = null;
        try {
            in = new FileInputStream(wsdlFile);
            WSDL11ToAxisServiceBuilder wsdl11Builder = new WSDL11ToAxisServiceBuilder(in);
            if (axisConf != null) {
            	wsdl11Builder.useAxisConfiguration(axisConf);
            }
            AxisService service = wsdl11Builder.populateService();
            assertNotNull("Could not load AxisService from wsdl: " + wsdlFile.getAbsolutePath(), service);
            
            return service;
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
    
    private void checkOperationActions(AxisService service, AxisOperation operation, String expectedInputAction, String expectedOutputAction, String expectedFaultAction) {
        assertEquals(String.format("Expected that operation '%s' of service '%s' defines an input action of '%s' but it defines '%s' instead.", operation.getName(), service.getName(), expectedInputAction, operation.getInputAction()), expectedInputAction, operation.getInputAction());
        assertEquals(String.format("Expected that operation '%s' of service '%s' defines an output action of '%s' but it defines '%s' instead.", operation.getName(), service.getName(), expectedOutputAction, operation.getOutputAction()), expectedOutputAction, operation.getOutputAction());
        assertEquals(String.format("Expected that operation '%s' of service '%s' defines an input action of '%s' but it defines '%s' instead.", operation.getName(), service.getName(), expectedFaultAction, operation.getFaultAction()), expectedFaultAction, operation.getFaultAction());
        
        ArrayList<String> wsaMappingList = operation.getWSAMappingList();
        assertEquals(String.format("Expected that operation '%s' of service '%s' has a 'wsaMappingList' of size '%d' but size is '%d' instead.", operation.getName(), service.getName(), 1, wsaMappingList.size()), 1, wsaMappingList.size());
        assertTrue(String.format("Expected that the 'wsaMappingList' of operation '%s' of service '%s' contains an entry of '%s' but it does not.", operation.getName(), service.getName(), expectedInputAction), wsaMappingList.contains(expectedInputAction));
        
        assertSame(String.format("Expected that 'operationsAliasesMap' of service '%s' contains a '%s' operation for action '%s'.", service.getName(), operation.getName(), expectedInputAction), service.getOperationByAction(expectedInputAction), operation);
    }
    
    public void testGetVersionActions() throws IOException {
    	AxisConfiguration axisConf = new AxisConfiguration();
        AxisService service = populateAxisService(axisConf, new File("test-resources/wsdl/Version.wsdl"));
        
        String[] operationNames = new String[] { 
        		"getVersionWSAW", "getVersionWSA", "getVersionWSAM", "getVersionWSAWSubmission", 
        		"getVersionWSAWURI", "getVersionWSAURI", "getVersionWSAMURI", "getVersionWSAWSubmissionURI" 
        };
        
        for (String operationName : operationNames) {
	        QName operationQName = new QName("http://axisversion.sample", operationName);
	        AxisOperation operation = service.getOperation(operationQName);
	        assertNotNull(String.format("Could not find AxisOperation '%s' in service: %s", operationQName.toString(), service.getName()), operation);
	
	        String prefix = operationName.endsWith("URI") ? "ns:Version" : "http://axisversion.sample";
	        String expectedInputAction = String.format("%s/VersionPortType/%sRequest", prefix, operationQName.getLocalPart());
	        String expectedOutputAction = String.format("%s/VersionPortType/%sResponse", prefix, operationQName.getLocalPart());
	        String expectedFaultAction = String.format("%s/VersionPortType/Fault/%sException", prefix, operationQName.getLocalPart());
	        
	        checkOperationActions(service, operation, expectedInputAction,expectedOutputAction,expectedFaultAction);
        }
    }
    
    /**
     * Tests parsing of <code>EchoService.wsdl</code> into an AxisService instance. The <code>EchoService.wsdl</code>
     * imports <code>EchoBindings.wsdl</code>, which contains the binding definitions (note that it does not reverse-import the EchoService.wsdl).
     * Parsing the wsdl should cause neither a "There is no port type associated with the binding" exception, nor a "Cannot determine the MEP" exception,
     * provided that Axis2 does not recursively search the port type in all imported wsdls, but looks it up via {@link javax.wsdl.Definition#getPortType(QName)}, 
     * falling back to {@link javax.wsdl.Binding#getPortType()} if not available (will be the case when port type is imported through another document but not directly)
     *
     * The test verifies that no exceptions are thrown and additionally checks that the endpoint, binding, operation and its in/out messages are correctly populated from the WSDL definition.
     * @throws IOException
     */
    public void testImportedBindings() throws IOException {
        AxisConfiguration axisConf = new AxisConfiguration();
        WSDLLocator wsdlLocator = new CustomWSDLLocator("test-resources/wsdl/imports/binding/", "EchoService.wsdl");
        AxisService service = populateAxisService(axisConf, new File(wsdlLocator.getBaseURI()), wsdlLocator);
        assertValidEchoService(service, wsdlLocator);
    }
    
    /**
     * Tests parsing of <code>EchoService.wsdl</code> into an AxisService instance. The <code>EchoService.wsdl</code>
     * imports <code>EchoBindings.wsdl</code>, which reverse-imports the EchoService.wsdl (i.e. we have a circular import).
     * Parsing the wsdl should cause neither a "There is no port type associated with the binding" exception, nor a "Cannot determine the MEP" exception,
     * provided that Axis2 does not recursively search the port type in all imported wsdls, but looks it up via {@link javax.wsdl.Definition#getPortType(QName)}, 
     * falling back to {@link javax.wsdl.Binding#getPortType()} if not available (will be the case when port type is imported through another document but not directly)
     *
     * The test verifies that no exceptions are thrown and additionally checks that the endpoint, binding, operation and its in/out messages are correctly populated from the WSDL definition.
     * @throws IOException
     */
    public void testCircularImportedBindings() throws IOException {
        AxisConfiguration axisConf = new AxisConfiguration();
        WSDLLocator wsdlLocator = new CustomWSDLLocator("test-resources/wsdl/imports/binding_recursive/", "EchoService.wsdl");
        AxisService service = populateAxisService(axisConf, new File(wsdlLocator.getBaseURI()), wsdlLocator);
        assertValidEchoService(service, wsdlLocator);
    }
    
    /**
     * Tests parsing of <code>EchoService.wsdl</code> into an AxisService instance. The <code>EchoService.wsdl</code>
     * imports <code>EchoBindings.wsdl</code>, which in turn imports the <code>EchoPortType.wsdl</code>.
     * Parsing the wsdl should cause neither a "There is no port type associated with the binding" exception, nor a "Cannot determine the MEP" exception,
     * provided that Axis2 does not recursively search the port type in all imported wsdls, but looks it up via {@link javax.wsdl.Definition#getPortType(QName)}, 
     * falling back to {@link javax.wsdl.Binding#getPortType()} if not available (will be the case when port type is imported through another document but not directly)
     *
     * The test verifies that no exceptions are thrown and additionally checks that the endpoint, binding, operation and its in/out messages are correctly populated from the WSDL definition.
     * @throws IOException
     */
    public void testImportedPortType() throws IOException {
        AxisConfiguration axisConf = new AxisConfiguration();
        WSDLLocator wsdlLocator = new CustomWSDLLocator("test-resources/wsdl/imports/portType/", "EchoService.wsdl");
        AxisService service = populateAxisService(axisConf, new File(wsdlLocator.getBaseURI()), wsdlLocator);
        assertValidEchoService(service, wsdlLocator);
    }
    
    private void assertValidEchoService(AxisService echoService, WSDLLocator wsdlLocator) {
        //check soap12 endpoint and binding are available
        String endpointName = "EchoServiceHttpSoap12Endpoint";
        AxisEndpoint soap12Endpoint = echoService.getEndpoint(endpointName);
        assertNotNull(String.format("Cannot find %s endpoint in wsdl definition: %s", endpointName, wsdlLocator.getBaseURI()), soap12Endpoint);
        
        AxisBinding soap12Binding = soap12Endpoint.getBinding();
        assertNotNull(String.format("Binding not set on %s endpoint in wsdl definition: %s", endpointName, wsdlLocator.getBaseURI()), soap12Binding);
        
        //check that policy reference is present on the binding subject
        String bindingPolicyRefId = "#basicAuthPolicy";
        assertNotNull(String.format("Cannot find policy reference %s on binding %s", bindingPolicyRefId, soap12Binding.getName()),
                soap12Binding.getPolicySubject().getAttachedPolicyComponent(bindingPolicyRefId));
        
        //check that binding operation and respective operation are available
        QName echoBindingOpName = new QName("http://tempuri.org/bindings", "echo");
        AxisBindingOperation echoBindingOp = (AxisBindingOperation) soap12Binding.getChild(echoBindingOpName);
        assertNotNull(String.format("Cannot find %s binding operation on binding %s",  echoBindingOpName, soap12Binding), echoBindingOp);
        
        AxisOperation echoOp = echoBindingOp.getAxisOperation();
        assertNotNull(String.format("Operation not set on binding operation %s",  echoBindingOp.getName()), echoOp);
        
        //check that operation style is correctly identified and an operation with respective mep is created
        assertTrue(String.format("Operation %s is not an instance of %s", echoOp.getName(), InOutAxisOperation.class.getName()), echoOp instanceof InOutAxisOperation);
        assertEquals(String.format("Operation %s specifies an unexpected MEP uri: %s", echoOp.getName(), echoOp.getMessageExchangePattern()), 
                WSDL2Constants.MEP_URI_IN_OUT, echoOp.getMessageExchangePattern());
        
        //check in/out messages
        AxisMessage inMessage =  echoOp.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
        assertNotNull(String.format("No input message set on operation %s", echoOp.getName()), inMessage);
        QName echoInMessageName = new QName("http://tempuri.org/types", "echo");
        assertEquals(String.format("Unexpected input message QName set on operation %s", echoOp.getName()), echoInMessageName, inMessage.getElementQName());
        //message name is 'echoRequest' whereas the QName's local name is simply 'echo'
        assertEquals(String.format("Unexpected input message name set on operation %s", echoOp.getName()), "echoRequest", inMessage.getName());
        
        AxisMessage outMessage =  echoOp.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        assertNotNull(String.format("No output message set on operation %s", echoOp.getName()), outMessage);
        QName echoOutMessageName = new QName("http://tempuri.org/types", "echoResponse");
        assertEquals(String.format("Unexpected output message QName set on operation %s", echoOp.getName()), echoOutMessageName, outMessage.getElementQName());
        assertEquals(String.format("Unexpected output message name set on operation %s", echoOp.getName()), echoOutMessageName.getLocalPart(), outMessage.getName());
    }
    
    private AxisService populateAxisService(AxisConfiguration axisConf, File wsdlFile, WSDLLocator wsdlLocator) throws IOException {
        InputStream in = null;
        try {
            in = new FileInputStream(wsdlFile);
            WSDL11ToAxisServiceBuilder wsdl11Builder = new WSDL11ToAxisServiceBuilder(in);
            if (wsdlLocator != null) {
                wsdl11Builder.setCustomWSDLResolver(wsdlLocator);
            }
            wsdl11Builder.setDocumentBaseUri(wsdlFile.getParentFile().toURI().toString());
            if (axisConf != null) {
                wsdl11Builder.useAxisConfiguration(axisConf);
            }
            AxisService service = wsdl11Builder.populateService();
            assertNotNull("Could not load AxisService from wsdl: " + wsdlFile.getAbsolutePath(), service);
            
            return service;
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
    
    //custom locator that can located imported wsdls relative to the base wsdl uri (code borrowed from wsdl4j)
    class CustomWSDLLocator implements WSDLLocator {
        private String wsdlURI;

        private InputSource baseInputSource;
        private Map<String, InputSource> importInputSources = new HashMap<String, InputSource>();
        private boolean closed = false;
        private String baseURI;
        private String lastImportURI;

        public CustomWSDLLocator(String baseURI, String wsdlURI) {
            this.baseURI = baseURI;
            this.wsdlURI = wsdlURI;
        }

        public InputSource getBaseInputSource() {
            if (baseInputSource == null) {
                lastImportURI = baseURI + wsdlURI;
                baseInputSource = new InputSource(lastImportURI);
            }
            return baseInputSource;
        }

        public InputSource getImportInputSource(String parentLocation, String importLocation) {
            InputSource inSource = (InputSource) importInputSources.get(importLocation);
            if (inSource == null) {
                lastImportURI = baseURI + importLocation;
                inSource = new InputSource(lastImportURI);
                importInputSources.put(importLocation, inSource);
            }
            return inSource;
        }

        public String getBaseURI() {
            return baseURI + wsdlURI;
        }

        public String getLatestImportURI() {
            return lastImportURI;
        }

        public void close() {
            closed = true;
        }

        public boolean isClosed() {
            return closed;
        }
    }
}
