/*******************************************************************************
 * Copyright (c) 2006, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.wst.wsdl.tests;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.wsdl.OperationType;
import javax.wsdl.Port;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.xml.WSDLReader;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.wst.wsdl.Binding;
import org.eclipse.wst.wsdl.BindingFault;
import org.eclipse.wst.wsdl.BindingInput;
import org.eclipse.wst.wsdl.BindingOperation;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.ExtensibleElement;
import org.eclipse.wst.wsdl.Fault;
import org.eclipse.wst.wsdl.Import;
import org.eclipse.wst.wsdl.Input;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Output;
import org.eclipse.wst.wsdl.Part;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.Service;
import org.eclipse.wst.wsdl.Types;
import org.eclipse.wst.wsdl.WSDLFactory;
import org.eclipse.wst.wsdl.WSDLPackage;
import org.eclipse.wst.wsdl.WSDLPlugin;
import org.eclipse.wst.wsdl.XSDSchemaExtensibilityElement;
import org.eclipse.wst.wsdl.binding.mime.MIMEContent;
import org.eclipse.wst.wsdl.binding.mime.MIMEFactory;
import org.eclipse.wst.wsdl.binding.mime.MIMEMimeXml;
import org.eclipse.wst.wsdl.binding.mime.MIMEMultipartRelated;
import org.eclipse.wst.wsdl.binding.mime.MIMEPackage;
import org.eclipse.wst.wsdl.binding.mime.MIMEPart;
import org.eclipse.wst.wsdl.binding.mime.internal.util.MIMEConstants;
import org.eclipse.wst.wsdl.binding.soap.SOAPBody;
import org.eclipse.wst.wsdl.binding.soap.SOAPFactory;
import org.eclipse.wst.wsdl.binding.soap.SOAPPackage;
import org.eclipse.wst.wsdl.binding.soap.internal.util.SOAPConstants;
import org.eclipse.wst.wsdl.tests.util.DefinitionLoader;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * Contains unit tests for reported bugs.
 */
public class BugFixesTest extends TestCase
{
  private String PLUGIN_ABSOLUTE_PATH = WSDLTestsPlugin.getInstallURL();

  public BugFixesTest(String name)
  {
    super(name);
  }

  public static void main(String[] args)
  {
    junit.textui.TestRunner.run(suite());
  }

  public static Test suite()
  {
    TestSuite suite = new TestSuite();

    suite.addTest(new BugFixesTest("TypeAndElementResolution") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testTypeAndElementResolution();
        }
      });

    suite.addTest(new BugFixesTest("MIMEGetTypeName") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testReturnsProperQNameForMIMEExtensibilityElements();
        }
      });

    suite.addTest(new BugFixesTest("ImportsElementOrder") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testPlacesImportsAfterTheDefinitionElement();
        }
      });

    suite.addTest(new BugFixesTest("ResolveWSDLElement") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testResolvesElementInImports();
        }
      });

    suite.addTest(new BugFixesTest("PartsSerialization") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testSerializesPartsInSOAPBody();
        }
      });

    suite.addTest(new BugFixesTest("ImportsSerialization") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testSerializesImportsBeforeTypes();
        }
      });

    suite.addTest(new BugFixesTest("LocalNamespacePrefixes") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testSupportsLocalNamespacePrefixes();
        }
      });

    suite.addTest(new BugFixesTest("OperationExtensionElements") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testTolleratesExtensionElementsForOperation();
        }
      });

    suite.addTest(new BugFixesTest("ReconcilesBindingFaults") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testReconcilesBindingFaults();
        }
      });

    suite.addTest(new BugFixesTest("DuplicateSAXErrorDiagnostics") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testAvoidDuplicateSAXExceptionDiagnostics();
        }
      });

    suite.addTest(new BugFixesTest("BindingOperationReconciliation") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testBindingOperationReconciliation();
        }
      });

    suite.addTest(new BugFixesTest("FullElementExtensibility") //$NON-NLS-1$
      {
        protected void runTest()
        {
          testFullElementExtensibility();
        }
      });

    suite.addTest(new BugFixesTest("TypesExtensibility") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testTypesExtensibility();
      }
    });

    suite.addTest(new BugFixesTest("AllowNullNamespaceURI") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testAllowNullNamespaceURI();
      }
    });

    suite.addTest(new BugFixesTest("LoadsNamelessDefinition") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testLoadsNamelessDefinition();
      }
    });

    suite.addTest(new BugFixesTest("HandlesDocumentationElements") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testHandlesDocumentationElements();
      }
    });

    suite.addTest(new BugFixesTest("SupportsLocalNSForExtensibilityElements") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testSupportsLocalNSForExtensibilityElements();
      }
    });
    
    suite.addTest(new BugFixesTest("InlineTypesFromImportsAreVisible") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testInlineTypesFromImportsAreVisible();
      }
    });
    
    suite.addTest(new BugFixesTest("PropagatesTargetNamespaceChange") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testPropagatesTargetNamespaceChange();
      }
    });
    
    return suite;
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=133310
   */
  public void testTypeAndElementResolution()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/TypeAndElementResolution/Test.wsdl"); //$NON-NLS-1$

      // There are two inline schemas, each importing an external schema.
      // The first schema is empty and used just to show the type resolution
      // mechanism's fault.
      // The schema containing the type and element declaration we're interested
      // in is the second schema in the collection.

      XSDSchema inlineSchema = (XSDSchema)definition.getETypes().getSchemas().get(1);

      // The first and only component in this schema is an import.

      XSDImport xsdImport = (XSDImport)inlineSchema.getContents().get(0);

      // The imported schema was resolved when the resource was loaded.
      // This is the schema containing our type/element.

      XSDSchema schema = xsdImport.getResolvedSchema();

      // Now check to make sure the resolved type/element for the messages in
      // the WSDL document
      // are the ones in the schema and not some bogus ones.

      Iterator messagesIterator = definition.getEMessages().iterator();

      while (messagesIterator.hasNext())
      {
        Message message = (Message)messagesIterator.next();
        String name = message.getQName().getLocalPart();
        if (name.equals("testRequest")) //$NON-NLS-1$
        {
          // We know there is only one part in the message and it refers to a
          // type. Make sure the type can be resolved.

          Part part = (Part)message.getEParts().get(0);
          XSDTypeDefinition myType = part.getTypeDefinition();
          assertEquals(schema, myType.getContainer());
        }
        else if (name.equals("testResponse")) //$NON-NLS-1$
        {
          // We know there is only one part in the message and it refers to an
          // element.

          Part part = (Part)message.getEParts().get(0);
          XSDElementDeclaration myElement = part.getElementDeclaration();
          assertEquals(schema, myElement.getContainer());
        }
      }

    }
    catch (Exception e)
    {
      Assert.fail("Test failed due to an exception: " + e.getLocalizedMessage()); //$NON-NLS-1$
    }
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=133953
   */
  public void testReturnsProperQNameForMIMEExtensibilityElements()
  {
    MIMEFactory factory = MIMEPackage.eINSTANCE.getMIMEFactory();

    MIMEContent content = factory.createMIMEContent();
    QName contentElementType = content.getElementType();
    assertEquals(MIMEConstants.MIME_NAMESPACE_URI, contentElementType.getNamespaceURI());
    assertEquals(MIMEConstants.CONTENT_ELEMENT_TAG, contentElementType.getLocalPart());

    MIMEMimeXml mimeXml = factory.createMIMEMimeXml();
    QName mimeXmlElementType = mimeXml.getElementType();
    assertEquals(MIMEConstants.MIME_NAMESPACE_URI, mimeXmlElementType.getNamespaceURI());
    assertEquals(MIMEConstants.MIME_XML_ELEMENT_TAG, mimeXmlElementType.getLocalPart());

    MIMEMultipartRelated multipartRelated = factory.createMIMEMultipartRelated();
    QName multipartRelatedElementType = multipartRelated.getElementType();
    assertEquals(MIMEConstants.MIME_NAMESPACE_URI, multipartRelatedElementType.getNamespaceURI());
    assertEquals(MIMEConstants.MULTIPART_RELATED_ELEMENT_TAG, multipartRelatedElementType.getLocalPart());

    MIMEPart part = factory.createMIMEPart();
    QName partElementType = part.getElementType();
    assertEquals(MIMEConstants.MIME_NAMESPACE_URI, partElementType.getNamespaceURI());
    assertEquals(MIMEConstants.PART_ELEMENT_TAG, partElementType.getLocalPart());
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=137040
   */
  public void testPlacesImportsAfterTheDefinitionElement()
  {
    WSDLFactory factory = WSDLPackage.eINSTANCE.getWSDLFactory();

    String namespace = "testNamespace"; //$NON-NLS-1$

    Definition definition = factory.createDefinition();
    definition.setQName(new QName(namespace, "testDefinition")); //$NON-NLS-1$  
    definition.updateElement();

    Service service = factory.createService();
    service.setQName(new QName(namespace, "testService")); //$NON-NLS-1$
    definition.addService(service);

    Import wsdlImport = factory.createImport();
    definition.addImport(wsdlImport);

    Element definitionElement = definition.getElement();
    Element serviceElement = service.getElement();
    Element importElement = wsdlImport.getElement();

    NodeList definitionElementChildren = definitionElement.getChildNodes();

    Node firstChild = definitionElementChildren.item(0);

    assertSame(importElement, firstChild);

    Node secondChild = definitionElementChildren.item(1);

    assertSame(serviceElement, secondChild);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=137866
   */
  public void testResolvesElementInImports()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/WSDLElementResolution/main.wsdl"); //$NON-NLS-1$

      String targetNamespace = "http://www.example.com"; //$NON-NLS-1$

      // This test attempts to locate a message located in the first level
      // import.

      QName firstLevelMessageQName = new QName(targetNamespace, "testINPUTmessage"); //$NON-NLS-1$
      javax.wsdl.Message firstLevelMessage = definition.getMessage(firstLevelMessageQName);

      assertNotNull(firstLevelMessage);

      // This test attempts to locate a message located in the second level
      // import.

      QName secondLevelMessageQName = new QName(targetNamespace, "testOUTPUTmessage"); //$NON-NLS-1$
      javax.wsdl.Message secondLevelMessage = definition.getMessage(secondLevelMessageQName);

      assertNotNull(secondLevelMessage);

      // This test ensures that we do a breadth first traversal to keep things
      // working approximatively as the old implementation which used to check
      // only the definition and its first level imports. The first message is
      // defined in firstlevel.wsdl as well as secondlevel.wsdl but the
      // algorithm should find the one in firstlevel.wsdl.

      Import firstLevelImport = (Import)definition.getImports(targetNamespace).get(0);
      Definition firstLevelDefinition = firstLevelImport.getEDefinition();

      assertEquals(firstLevelDefinition, ((Message)firstLevelMessage).getEnclosingDefinition());
    }
    catch (Exception e)
    {
      Assert.fail("Test failed due to an exception: " + e.getLocalizedMessage()); //$NON-NLS-1$
    }
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=137990
   */
  public void testSerializesPartsInSOAPBody()
  {
    // Build an in-memory WSDL definition.

    WSDLFactory factory = WSDLPackage.eINSTANCE.getWSDLFactory();

    String targetNamespace = "testNamespace"; //$NON-NLS-1$

    Definition definition = factory.createDefinition();
    definition.setTargetNamespace(targetNamespace);
    definition.setQName(new QName(targetNamespace, "testDefinition")); //$NON-NLS-1$
    definition.addNamespace("tns", targetNamespace); //$NON-NLS-1$
    definition.addNamespace("xsd", XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001); //$NON-NLS-1$
    definition.addNamespace("soap", SOAPConstants.SOAP_NAMESPACE_URI); //$NON-NLS-1$

    Message message = factory.createMessage();
    QName messageQName = new QName(targetNamespace, "testMessage");
    message.setQName(messageQName);
    definition.addMessage(message);

    Part part1 = factory.createPart();
    String part1Name = "part1"; //$NON-NLS-1$ 
    part1.setName(part1Name);
    part1.setTypeName(new QName(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, "string")); //$NON-NLS-1$
    message.addPart(part1);

    Part part2 = factory.createPart();
    String part2Name = "part2"; //$NON-NLS-1$ 
    part2.setName(part2Name);
    part2.setTypeName(new QName(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, "string")); //$NON-NLS-1$
    message.addPart(part2);

    PortType portType = factory.createPortType();
    QName portQName = new QName(targetNamespace, "testPort"); //$NON-NLS-1$
    portType.setQName(portQName);
    definition.addPortType(portType);

    Operation operation = factory.createOperation();
    String operationName = "testOperation"; //$NON-NLS-1$ 
    operation.setName(operationName);
    portType.addOperation(operation);

    Input input = factory.createInput();
    input.setMessage(message);
    operation.setInput(input);

    Binding binding = factory.createBinding();
    QName bindingQName = new QName(targetNamespace, "testBinding"); //$NON-NLS-1$
    binding.setQName(bindingQName);
    binding.setPortType(portType);
    definition.addBinding(binding);

    BindingOperation bindingOperation = factory.createBindingOperation();
    bindingOperation.setOperation(operation);
    binding.addBindingOperation(bindingOperation);

    BindingInput bindingInput = factory.createBindingInput();
    bindingOperation.setBindingInput(bindingInput);

    SOAPFactory soapFactory = SOAPPackage.eINSTANCE.getSOAPFactory();
    SOAPBody soapBody = soapFactory.createSOAPBody();
    bindingInput.addExtensibilityElement(soapBody);

    definition.updateElement();

    // Test the "no parts" scenario. In this case the parts attribute should not
    // be present.

    Element soapBodyElement = soapBody.getElement();
    Attr partsAttributeNode = soapBodyElement.getAttributeNode(SOAPConstants.PARTS_ATTRIBUTE);
    assertNull(partsAttributeNode);

    // Test the scenario when the body specifies one part. In this case the
    // parts attribute
    // should be present and look like this parts="part1"

    List parts = new ArrayList();
    parts.add(part1);
    soapBody.setParts(parts);

    soapBody.updateElement();

    soapBodyElement = soapBody.getElement();
    String partsAttributeValue = soapBodyElement.getAttribute(SOAPConstants.PARTS_ATTRIBUTE);
    assertEquals(part1Name, partsAttributeValue);

    // Test the scenario when the body specifies two parts. In this case the
    // parts attribute
    // should be present and look like this parts="part1 part2"

    parts.add(part2);
    soapBody.setParts(parts);

    soapBody.updateElement();

    soapBodyElement = soapBody.getElement();
    partsAttributeValue = soapBodyElement.getAttribute(SOAPConstants.PARTS_ATTRIBUTE);
    assertEquals(part1Name + " " + part2Name, partsAttributeValue); //$NON-NLS-1$
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=138033
   */
  public void testSerializesImportsBeforeTypes()
  {
    WSDLFactory factory = WSDLPackage.eINSTANCE.getWSDLFactory();

    String namespace = "testNamespace"; //$NON-NLS-1$

    Definition definition = factory.createDefinition();
    definition.setQName(new QName(namespace, "testDefinition")); //$NON-NLS-1$  
    definition.updateElement();

    Types types = factory.createTypes();
    definition.setTypes(types);

    Import wsdlImport = factory.createImport();
    definition.addImport(wsdlImport);

    Element definitionElement = definition.getElement();
    Element typesElement = types.getElement();
    Element importElement = wsdlImport.getElement();

    NodeList definitionElementChildren = definitionElement.getChildNodes();

    Node firstChild = definitionElementChildren.item(0);

    assertSame(importElement, firstChild);

    Node secondChild = definitionElementChildren.item(1);

    assertSame(typesElement, secondChild);

    // Blow away the backing DOM.

    definition.setElement(null);
    definition.updateElement();

    definitionElement = definition.getElement();
    typesElement = types.getElement();
    importElement = wsdlImport.getElement();

    definitionElementChildren = definitionElement.getChildNodes();

    firstChild = definitionElementChildren.item(0);

    assertSame(importElement, firstChild);

    secondChild = definitionElementChildren.item(1);

    assertSame(typesElement, secondChild);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=150553
   */
  public void testSupportsLocalNamespacePrefixes()
  {
    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/LocalNamespace/LocalNamespace.wsdl"); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    String targetNamespace = "http://tempuri.org/Simple/"; //$NON-NLS-1$

    // Check that the response message's part element is resolved OK.

    QName responseMessageQName = new QName(targetNamespace, "myOperationResponse"); ////$NON-NLS-1$
    javax.wsdl.Message responseMessage = definition.getMessage(responseMessageQName);

    Part responsePart = (Part)responseMessage.getPart("myOperationResponse"); ////$NON-NLS-1$

    XSDElementDeclaration responseElementDeclaration = responsePart.getElementDeclaration();

    assertNotNull(responseElementDeclaration);
    assertNotNull(responseElementDeclaration.getContainer());

    // Check that the request message's part element is resolved OK.
    // This part defines a local namespace prefix

    QName requestMessageQName = new QName(targetNamespace, "myOperationRequest"); ////$NON-NLS-1$
    javax.wsdl.Message requestMessage = definition.getMessage(requestMessageQName);

    Part requestPart = (Part)requestMessage.getPart("myOperationRequest"); ////$NON-NLS-1$

    XSDElementDeclaration requestElementDeclaration = requestPart.getElementDeclaration();

    assertNotNull(requestElementDeclaration);

    // Now to make sure the DOM is reconciled properly and uses the local namespace prefix, 
    // let's try to change the part's element declaration. We'll use the response part element
    // just because it is convenient.

    requestPart.setElementDeclaration(responseElementDeclaration);

    Element partElement = requestPart.getElement();
    String elementAttributeValue = partElement.getAttribute(WSDLConstants.ELEMENT_ATTRIBUTE);

    assertEquals(elementAttributeValue, "parttns:" + responseElementDeclaration.getName());
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=157107
   */
  public void testTolleratesExtensionElementsForOperation()
  {
    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/OperationStyle/OperationStyleTest.wsdl"); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    PortType portType = (PortType)definition.getEPortTypes().get(0);
    EList operations = portType.getEOperations();

    Operation operation = (Operation)operations.get(0);
    OperationType operationType = operation.getStyle();

    assertEquals(OperationType.REQUEST_RESPONSE, operationType);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=164565
   */
  public void testReconcilesBindingFaults()
  {
    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/BindingFaultReconciliation/BindingFaultSample.wsdl"); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    // Test the abnormal case when the binding operation tries to bind a fault
    // but the fault is missing in the corresponding operation. In this case the
    // fault obtained from the binding operation's fault should be null.

    List bindings = definition.getEBindings();
    Binding binding = (Binding)bindings.get(0);
    List bindingOperations = binding.getBindingOperations();
    BindingOperation bindingOperation = (BindingOperation)bindingOperations.get(0);
    BindingFault bindingFault = (BindingFault)bindingOperation.getBindingFault("Operation1Fault"); //$NON-NLS-1$
    Fault fault = bindingFault.getEFault();
    assertNull(fault);

    // Test the normal case when the operation and binding operation are in
    // synch. In this case the fault defined in the operation should match
    // the one obtained from the binding operation's fault.

    List portTypes = definition.getEPortTypes();
    PortType portType = (PortType)portTypes.get(0);
    EList operations = portType.getEOperations();

    Operation operation = (Operation)operations.get(1);
    javax.wsdl.Fault expectedFault1 = operation.getFault("Operation2Fault1"); //$NON-NLS-1$
    javax.wsdl.Fault expectedFault2 = operation.getFault("Operation2Fault2"); //$NON-NLS-1$

    BindingOperation bindingOperation2 = (BindingOperation)bindingOperations.get(1);

    // Make sure the fault obtained from the binding fault is not null and
    // matches the one in the corresponding operation.

    BindingFault bindingFault1 = (BindingFault)bindingOperation2.getBindingFault("Operation2Fault1"); //$NON-NLS-1$
    javax.wsdl.Fault actualFault1 = bindingFault1.getEFault();
    assertNotNull(actualFault1);
    assertEquals(expectedFault1, actualFault1);

    // Make sure the fault obtained from the binding fault is not null and
    // matches the one in the corresponding operation.

    BindingFault bindingFault2 = (BindingFault)bindingOperation2.getBindingFault("Operation2Fault2"); //$NON-NLS-1$
    javax.wsdl.Fault actualFault2 = bindingFault2.getEFault();
    assertNotNull(actualFault2);
    assertEquals(expectedFault2, actualFault2);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=161059
   */
  public void testAvoidDuplicateSAXExceptionDiagnostics()
  {
    Definition definition = null;

    try
    {
      // Make sure we track location to allow the WSDLParser to kick in.

      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/DuplicateSAXException/SAXException.wsdl", true, true); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    Resource resource = definition.eResource();
    EList errors = resource.getErrors();
    int expectedSize = 1;
    int actualSize = errors.size();
    assertEquals(expectedSize, actualSize);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=172576
   */
  public void testBindingOperationReconciliation()
  {
    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH
        + "samples/BugFixes/BindingOperationReconciliation/BindingOperationReconciliation.wsdl", true); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    String targetNamespace = "http://www.example.org/BindingOperationReconciliation/"; //$NON-NLS-1$
    QName portTypeQName = new QName(targetNamespace, "BindingOperationReconciliation"); //$NON-NLS-1$
    javax.wsdl.PortType portType = definition.getPortType(portTypeQName);

    String input3Name = "Input3"; //$NON-NLS-1$
    String output3Name = "Output3"; //$NON-NLS-1$

    // Check that the first operation - which has no named input/output is being
    // found.

    String operationName = "NewOperation"; //$NON-NLS-1$
    javax.wsdl.Operation operation1 = portType.getOperation(operationName, null, null);

    QName bindingQName = new QName(targetNamespace, "BindingOperationReconciliationSOAP"); //$NON-NLS-1$
    javax.wsdl.Binding binding = definition.getBinding(bindingQName);

    javax.wsdl.BindingOperation bindingOperation1 = binding.getBindingOperation(operationName, null, null);
    javax.wsdl.Operation actualOperation1 = bindingOperation1.getOperation();

    assertEquals(operation1, actualOperation1);

    // The second operation - which has no named input/output is being found
    // should not be reconciled because the binding specifies the input and
    // output.

    String input2Name = "Input2"; //$NON-NLS-1$
    String output2Name = "Output2"; //$NON-NLS-1$

    String operation2Name = "NewOperation2"; //$NON-NLS-1$

    javax.wsdl.BindingOperation bindingOperation2 = binding.getBindingOperation(operation2Name, input2Name, output2Name);
    javax.wsdl.Operation actualOperation2 = bindingOperation2.getOperation();

    assertEquals(null, actualOperation2);

    // The third operation specifies an input and output name, and the binding
    // operation will reconcile fine because the it also specifies the proper
    // input and output name.

    String operation3Name = "NewOperation3"; //$NON-NLS-1$
    javax.wsdl.Operation operation3 = portType.getOperation(operation3Name, input3Name, output3Name);

    javax.wsdl.BindingOperation bindingOperation3 = binding.getBindingOperation(operation3Name, input3Name, output3Name);
    javax.wsdl.Operation actualOperation3 = bindingOperation3.getOperation();

    assertEquals(operation3, actualOperation3);
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=177852
   */
  public void testFullElementExtensibility()
  {

    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/FullElementExtensibility/ExtendedWSDL.wsdl", true); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    String extensionsNamespaceURI = "http://www.example.org/Extensions/"; //$NON-NLS-1$ 
    EList imports = definition.getEImports();
    assertFalse(imports.isEmpty());
    Import theImport = (Import)imports.get(0);
    checkExtension(theImport, extensionsNamespaceURI, "import"); //$NON-NLS-1$

    EList messages = definition.getEMessages();
    assertFalse(messages.isEmpty());
    Message message = (Message)messages.get(0);
    checkExtension(message, extensionsNamespaceURI, "message"); //$NON-NLS-1$

    Part part = (Part)message.getPart("extendedPart"); //$NON-NLS-1$
    assertNotNull(part);
    checkExtension(part, extensionsNamespaceURI, "part"); //$NON-NLS-1$

    EList portTypes = definition.getEPortTypes();
    assertFalse(portTypes.isEmpty());
    PortType portType = (PortType)portTypes.get(0);
    checkExtension(portType, extensionsNamespaceURI, "portType"); //$NON-NLS-1$

    Operation operation = (Operation)portType.getOperation("extendedOperation", null, null); //$NON-NLS-1$
    assertNotNull(operation);
    checkExtension(operation, extensionsNamespaceURI, "operation"); //$NON-NLS-1$

    Input input = operation.getEInput();
    assertNotNull(input);
    checkExtension(input, extensionsNamespaceURI, "input"); //$NON-NLS-1$

    Output output = operation.getEOutput();
    assertNotNull(output);
    checkExtension(output, extensionsNamespaceURI, "output"); //$NON-NLS-1$

    Fault fault = (Fault)operation.getFault("extendedFault"); //$NON-NLS-1$
    assertNotNull(fault);
    checkExtension(fault, extensionsNamespaceURI, "fault"); //$NON-NLS-1$
  }

  /**
   * Checks the given extensible element to make sure that its assumed one and only extensibility element matches the given namespace and local name.
   * @param extensibleElement the extensible element to test.
   * @param extensionsNamespaceURI the expected namespace URI.
   * @param elementName the expected element name.
   */
  private void checkExtension(ExtensibleElement extensibleElement, String extensionsNamespaceURI, String elementName)
  {
    List extensibilityElements = extensibleElement.getExtensibilityElements();
    assertFalse(extensibilityElements.isEmpty());
    ExtensibilityElement extensibilityElement = (ExtensibilityElement)extensibilityElements.get(0);
    QName elementType = extensibilityElement.getElementType();
    String nsURI = elementType.getNamespaceURI();
    String localPart = elementType.getLocalPart();
    assertEquals(extensionsNamespaceURI, nsURI);
    assertEquals(localPart, elementName);
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=174361
   */
  public void testTypesExtensibility()
  {

    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/TypesExtensibility/TypesExtensibility.wsdl", true); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }
    
    Types types = definition.getETypes();
    List extensibilityElements = types.getExtensibilityElements();
    assertEquals(3, extensibilityElements.size());
    
    String otherTypesNamespace = "http://www.example.org/OtherTypes/"; //$NON-NLS-1$

    ExtensibilityElement extensibilityElement = (ExtensibilityElement)extensibilityElements.get(0);
    QName elementType = extensibilityElement.getElementType();
    assertEquals(otherTypesNamespace, elementType.getNamespaceURI());
    assertEquals("typeDef", elementType.getLocalPart()); //$NON-NLS-1$

    List schemas = types.getSchemas();
    assertEquals(1, schemas.size());
    
    XSDSchemaExtensibilityElement schemaExtensibilityElement = (XSDSchemaExtensibilityElement)extensibilityElements.get(1);
    XSDSchema schema = schemaExtensibilityElement.getSchema();
    assertNotNull(schema);
    XSDElementDeclaration elementDeclaration = schema.resolveElementDeclaration("test"); //$NON-NLS-1$
    assertNotNull(elementDeclaration);
    assertNotNull(elementDeclaration.getContainer());    
    
    extensibilityElement = (ExtensibilityElement)extensibilityElements.get(2);
    elementType = extensibilityElement.getElementType();
    assertEquals(otherTypesNamespace, elementType.getNamespaceURI());
    assertEquals("typeDef", elementType.getLocalPart()); //$NON-NLS-1$    
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=178555
   */
  public void testAllowNullNamespaceURI()
  {
    Definition definition = null;

    try
    {
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/NullNamespaceURI/ContactInfoService.wsdl", true); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      fail(e.getMessage());
    }

    String targetNamespace = "http://www.example.org/ContactInfoService"; //$NON-NLS-1$

    // The element declaration for the output message part is specified in a
    // schema with no target namespace. It should resolve fine and have a null
    // namespace URI.

    QName output1QName = new QName(targetNamespace, "updatePhoneNumberResponseMsg"); //$NON-NLS-1$
    Message output1Message = (Message)definition.getMessage(output1QName);
    assertNotNull(output1Message);

    Part part1 = (Part)output1Message.getPart("output1"); //$NON-NLS-1$
    assertNotNull(part1);

    QName output2ElementName = part1.getElementName();
    assertNotNull(output2ElementName);
    assertEquals(XMLConstants.NULL_NS_URI, output2ElementName.getNamespaceURI());

    XSDElementDeclaration output2ElementDeclaration = part1.getElementDeclaration();
    assertNotNull(output2ElementDeclaration);
    assertNotNull(output2ElementDeclaration.getContainer());
    assertNull(output2ElementDeclaration.getTargetNamespace());

    // The type definition for the output message part is specified in a
    // schema with no target namespace. It should resolve fine and have a null
    // namespace URI.

    QName output2QName = new QName(targetNamespace, "updateAddressResponseMsg"); //$NON-NLS-1$
    Message output2Message = (Message)definition.getMessage(output2QName);
    assertNotNull(output2Message);

    Part part2 = (Part)output2Message.getPart("output2"); //$NON-NLS-1$
    assertNotNull(part1);

    QName output2TypeName = part2.getTypeName();
    assertNotNull(output2TypeName);
    assertEquals(XMLConstants.NULL_NS_URI, output2TypeName.getNamespaceURI());

    XSDTypeDefinition output2TypeDefinition = part2.getTypeDefinition();
    assertNotNull(output2TypeDefinition);
    assertNotNull(output2TypeDefinition.getContainer());
    assertNull(output2TypeDefinition.getTargetNamespace());
  }
  
  /**
   * https://bugs.eclipse.org/bugs/show_bug.cgi?id=104453
   */
  public void testLoadsNamelessDefinition()
  {
    try
    {
      //Test with nameless definition
      
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/LoadsNamelessDefinition/MissingName.wsdl");
      assertNull(definition.getQName());

      //Test with named definition
      
      definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/LoadsNamelessDefinition/WithName.wsdl");
      assertNotNull(definition);
      QName name = definition.getQName(); 
      assertNotNull(name);
      assertEquals("WSDLFile", name.getLocalPart());
    }
    catch (Exception e)
    {
      Assert.fail("Test failed due to an exception: " + e.getLocalizedMessage());
    }
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=151674
   * @throws Exception
   */
  public void testHandlesDocumentationElements()
  {
    try
    {
      // Load a sample WSDL document that has documentation elements in all allowed places.
      
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/HandlesDocumentationElements/Documented.wsdl");
      
      // Make sure imports are added after the documentation element.
      
      WSDLFactory factory = WSDLFactory.eINSTANCE;
      Import anImport = factory.createImport();
      anImport.setNamespaceURI("http://www.test.com");
      definition.addImport(anImport);
      
      Element definitionDocumentationElement = definition.getDocumentationElement();
      assertNotNull(definitionDocumentationElement);
      Element expectedImportElement = getNextElement(definitionDocumentationElement);
      Element importElement = anImport.getElement();
      assertEquals(importElement, expectedImportElement);
      
      // This is a bit overkill since the documentation elements are handled in the base class WSDLElementImpl but...
      
      // Make sure new message parts are added after the documentation element and as the last element.

      Message aMessage = (Message)definition.getEMessages().get(0);
      Part newPart = factory.createPart();
      aMessage.addPart(newPart);

      Element messageElement = aMessage.getElement();

      Element messageDocumentationElement = aMessage.getDocumentationElement();
      assertNotNull(messageDocumentationElement);
      Element firstChildElement = getFirstChildElement(messageElement);
      assertEquals(messageDocumentationElement, firstChildElement);
      
      Element partElement = newPart.getElement();
      Element lastChildElement = getLastChildElement(messageElement);
      assertEquals(partElement, lastChildElement);
      
      // Make sure new operations are added after the documentation element and as the last element.

      PortType portType = (PortType)definition.getEPortTypes().get(0);
      Operation newOperation = factory.createOperation();
      portType.addOperation(newOperation);
      
      Element portTypeElement = portType.getElement();

      Element portTypeDocumentationElement = portType.getDocumentationElement();
      assertNotNull(portTypeDocumentationElement);
      firstChildElement = getFirstChildElement(portTypeElement);
      assertEquals(portTypeDocumentationElement, firstChildElement);
      
      Element newOperationElement = newOperation.getElement();
      lastChildElement = getLastChildElement(portTypeElement);
      assertEquals(newOperationElement, lastChildElement);
      
      // Make sure the output element is added after the documentation element and as the last element.
      
      Operation operation = (Operation)portType.getEOperations().get(0);
      Output output = factory.createOutput();
      operation.setOutput(output);

      Element operationElement = operation.getElement();

      Element operationDocumentationElement = operation.getDocumentationElement();
      assertNotNull(operationDocumentationElement);
      firstChildElement = getFirstChildElement(operationElement);
      assertEquals(operationDocumentationElement, firstChildElement);
      
      Element outputElement = output.getElement();
      lastChildElement = getLastChildElement(operationElement);
      assertEquals(outputElement, lastChildElement);
    }
    catch (Exception e)
    {
      Assert.fail("Test failed due to an exception: " + e.getLocalizedMessage());
    }
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=198390
   */
  public void testSupportsLocalNSForExtensibilityElements()
  {
    try
    {
      String uri = PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/LocalNamespace/LocalNamespace2.wsdl"; //$NON-NLS-1$
      javax.wsdl.factory.WSDLFactory factory = WSDLPlugin.INSTANCE.createWSDL4JFactory();
      WSDLReader wsdlReader = factory.newWSDLReader();
      javax.wsdl.Definition definition = wsdlReader.readWSDL(uri);

      String targetNamespace = "http://www.example.org/example/"; //$NON-NLS-1$

      // Test a local SOAP namespace prefix declaration.

      QName bindingQName = new QName(targetNamespace, "exampleSOAP"); //$NON-NLS-1$
      javax.wsdl.Binding binding = definition.getBinding(bindingQName);
      assertNotNull(binding);
      List extensibilityElements = binding.getExtensibilityElements();
      assertEquals(1, extensibilityElements.size());
      ExtensibilityElement soapBinding = (ExtensibilityElement)extensibilityElements.get(0);
      assertNotNull(soapBinding);
      QName bindingElementType = soapBinding.getElementType();
      assertNotNull(bindingElementType);
      String localPart = bindingElementType.getLocalPart();
      assertEquals(SOAPConstants.BINDING_ELEMENT_TAG, localPart);
      String namespaceURI = bindingElementType.getNamespaceURI();
      assertEquals(SOAPConstants.SOAP_NAMESPACE_URI, namespaceURI);
      assertTrue(soapBinding instanceof javax.wsdl.extensions.soap.SOAPBinding);

      // Test a default SOAP namespace declaration at the port level.

      QName serviceQName = new QName(targetNamespace, "example"); //$NON-NLS-1$
      javax.wsdl.Service service = definition.getService(serviceQName);
      Port port = service.getPort("exampleSOAP");
      extensibilityElements = port.getExtensibilityElements();
      assertEquals(1, extensibilityElements.size());
      ExtensibilityElement soapAddress = (ExtensibilityElement)extensibilityElements.get(0);
      assertNotNull(soapAddress);
      QName portElementType = soapAddress.getElementType();
      assertNotNull(portElementType);
      localPart = portElementType.getLocalPart();
      assertEquals(SOAPConstants.ADDRESS_ELEMENT_TAG, localPart);
      namespaceURI = portElementType.getNamespaceURI();
      assertEquals(SOAPConstants.SOAP_NAMESPACE_URI, namespaceURI);
      assertTrue(soapAddress instanceof javax.wsdl.extensions.soap.SOAPAddress);
    }
    catch (WSDLException e)
    {
      e.printStackTrace();
      fail();
    }
  }

  private Element getNextElement(Element anElement)
  {
    Node node = anElement.getNextSibling();
    while (node != null && node.getNodeType() != Node.ELEMENT_NODE)
    {
      node = node.getNextSibling();
    }
    return (Element)node;
  }

  private Element getFirstChildElement(Element anElement)
  {
    Node node = anElement.getFirstChild();
    while (node != null && node.getNodeType() != Node.ELEMENT_NODE)
    {
      node = node.getNextSibling();
    }
    return (Element)node;
  }

  private Element getLastChildElement(Element anElement)
  {
    Node node = anElement.getLastChild();
    while (node != null && node.getNodeType() != Node.ELEMENT_NODE)
    {
      node = node.getPreviousSibling();
    }
    return (Element)node;
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=208485
   */
  public void testInlineTypesFromImportsAreVisible()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/InlineTypesFromImportsAreVisible/A.wsdl"); //$NON-NLS-1$
      String targetNamespace = "http://A"; //$NON-NLS-1$
      QName messageQName = new QName(targetNamespace, "message" ); //$NON-NLS-1$
      javax.wsdl.Message message = definition.getMessage(messageQName);
      assertNotNull(message);
      Part part = (Part)message.getPart("parameters"); //$NON-NLS-1$
      assertNotNull(part);
      XSDTypeDefinition typeDefinition = part.getTypeDefinition();
      assertNotNull(typeDefinition);
      String namespace = typeDefinition.getTargetNamespace();
      assertEquals("http://B", namespace);
      assertEquals("BType", typeDefinition.getName());
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }

  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=194096
   */
  public void testPropagatesTargetNamespaceChange()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/TargetNamespace/TargetNamespace.wsdl", true); //$NON-NLS-1$
      
      String oldTargetNamespace = definition.getTargetNamespace();

      QName messageQName = new QName(oldTargetNamespace, "NewOperationRequest");
      javax.wsdl.Message message = definition.getMessage(messageQName);
      assertNotNull(message);

      QName portTypeQName = new QName(oldTargetNamespace, "TargetNamespace");
      javax.wsdl.PortType portType = definition.getPortType(portTypeQName);
      assertNotNull(portType);
      
      QName bindingQName = new QName(oldTargetNamespace, "TargetNamespaceSOAP");
      javax.wsdl.Binding binding = definition.getBinding(bindingQName);
      assertNotNull(binding);

      QName serviceQName = new QName(oldTargetNamespace, "TargetNamespace");
      javax.wsdl.Service service = definition.getService(serviceQName);
      assertNotNull(service);

      String newTargetNamespace = "http://www.example.org/NewTargetNamespace/"; 
      definition.setTargetNamespace(newTargetNamespace);
      Element definitionElement = definition.getElement();
      Attr targetNamespaceNode = definitionElement.getAttributeNode(WSDLConstants.TARGETNAMESPACE_ATTRIBUTE);
      assertNotNull(targetNamespaceNode);
      assertEquals(newTargetNamespace, targetNamespaceNode.getValue());
      
      messageQName = new QName(newTargetNamespace, messageQName.getLocalPart());
      message = definition.getMessage(messageQName);
      assertNotNull(message);
     
      portTypeQName = new QName(newTargetNamespace, portTypeQName.getLocalPart());
      portType = definition.getPortType(portTypeQName);
      assertNotNull(portType);

      bindingQName = new QName(newTargetNamespace, bindingQName.getLocalPart());
      binding = definition.getBinding(bindingQName);
      assertNotNull(binding);

      serviceQName = new QName(newTargetNamespace, serviceQName.getLocalPart());
      service = definition.getService(serviceQName);
      assertNotNull(service);
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
}
