/*******************************************************************************
 * Copyright (c) 2006, 2009 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 java.util.Map;

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.internal.util.WSDLUtil;
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.Document;
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();
      }
    });
    
    suite.addTest(new BugFixesTest("RemoveBinding") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testRemoveBinding();
      }
    });
    
    suite.addTest(new BugFixesTest("RemoveMessage") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testRemoveMessage();
      }
    });
    
    suite.addTest(new BugFixesTest("RemovePortType") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testRemovePortType();
      }
    });
    
    suite.addTest(new BugFixesTest("RemoveService") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testRemoveService();
      }
    });
    
    suite.addTest(new BugFixesTest("GetWSDLType") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testGetWSDLType();
      }
    });
    
    suite.addTest(new BugFixesTest("InvalidXSDImports") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testInvalidXSDImports();
      }
    });
    
    suite.addTest(new BugFixesTest("ReconcileNonWSDLElements") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testReconcileNonWSDLElements();
      }
    });        
    
    suite.addTest(new BugFixesTest("ReconcilesImportsWithNoLocation") //$NON-NLS-1$
    {
      protected void runTest()
      {
        testReconcilesImportsWithNoLocation();
      }
    });        

    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=245263
   */
  public void testRemoveMessage()
  {
    try
    {
      // load a wsdl that imports another wsdl
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/WSDL4JRemove/RemoveViaWSDL4J.wsdl", true); //$NON-NLS-1$
      String targetNamespace = definition.getTargetNamespace();
      String importedTargetNamespace = "http://www.example.org/ImportMe/"; //$NON-NLS-1$
      int totalMessages = 5;
      definition.updateElement();
      
      // make sure wsdl was loaded properly
      assertEquals("Initial messages were not properly loaded (checked via definition.getMessages())", totalMessages, definition.getMessages().size()); //$NON-NLS-1$
      assertEquals("Initial messages were not properly loaded (checked via definition.getEMessages())", totalMessages, definition.getEMessages().size()); //$NON-NLS-1$
      Element definitionElement = definition.getElement();
      NodeList messageElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.MESSAGE_ELEMENT_TAG);
      assertEquals("Initial messages were not properly loaded (checked via DOM)", totalMessages, messageElements.getLength()); //$NON-NLS-1$
      
      // make sure message we're going to remove currently exists
      QName messageQName = new QName(targetNamespace, "RemoveViaWSDL4JMessageExtra"); //$NON-NLS-1$
      javax.wsdl.Message message = definition.getMessage(messageQName);
      assertNotNull("Unable to find RemoveViaWSDL4JMessageExtra", message); //$NON-NLS-1$
      
      // remove the message
      javax.wsdl.Message removedMessage = definition.removeMessage(messageQName);
      assertEquals("Incorrect message removed", message, removedMessage); //$NON-NLS-1$
      
      // make sure message is gone
      javax.wsdl.Message nonexistMessage = definition.getMessage(messageQName);
      assertNull("RemoveViaWSDL4JMessageExtra still exists in model", nonexistMessage); //$NON-NLS-1$
      
      // make sure there is now 1 less message
      assertEquals("Message was not removed (checked via definition.getMessages())", totalMessages-1, definition.getMessages().size()); //$NON-NLS-1$
      assertEquals("Message was not removed (checked via definition.getEMessages())", totalMessages-1, definition.getEMessages().size()); //$NON-NLS-1$
      definitionElement = definition.getElement();
      messageElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.MESSAGE_ELEMENT_TAG);
      assertEquals("Message was not removed (checked via DOM)", totalMessages-1, messageElements.getLength()); //$NON-NLS-1$
      
      // make sure imported message we're going to remove currently exists
      messageQName = new QName(importedTargetNamespace, "ImportMeMessageExtra"); //$NON-NLS-1$
      message = definition.getMessage(messageQName);
      assertNotNull("Unable to find ImportMeMessageExtra", message); //$NON-NLS-1$
      
      // attempt to remove the imported message
      removedMessage = definition.removeMessage(messageQName);
      assertNull("ImportMeMessageExtra was incorrectly removed", removedMessage); //$NON-NLS-1$
      
      // make sure imported message still exists
      message = definition.getMessage(messageQName);
      assertNotNull("ImportMeMessageExtra no longer exists", message); //$NON-NLS-1$
      
      nonexistMessage = definition.removeMessage(new QName(targetNamespace, "doesntexist")); //$NON-NLS-1$
      assertNull("A non-existing message was removed", nonexistMessage); //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=245263
   */
  public void testRemoveService()
  {
    try
    {
      // load a wsdl that imports another wsdl
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/WSDL4JRemove/RemoveViaWSDL4J.wsdl", true); //$NON-NLS-1$
      String targetNamespace = definition.getTargetNamespace();
      String importedTargetNamespace = "http://www.example.org/ImportMe/"; //$NON-NLS-1$
      int totalServices = 2;
      definition.updateElement();
      
      // make sure wsdl was loaded properly
      assertEquals("Initial services were not properly loaded (checked via definition.getServices())", totalServices, definition.getServices().size()); //$NON-NLS-1$
      assertEquals("Initial services were not properly loaded (checked via definition.getEServices())", totalServices, definition.getEServices().size()); //$NON-NLS-1$
      Element definitionElement = definition.getElement();
      NodeList serviceElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.SERVICE_ELEMENT_TAG);
      assertEquals("Initial services were not properly loaded (checked via DOM)", totalServices, serviceElements.getLength()); //$NON-NLS-1$
      
      // make sure service we're going to remove currently exists
      QName serviceQName = new QName(targetNamespace, "MainServiceExtra"); //$NON-NLS-1$
      javax.wsdl.Service service = definition.getService(serviceQName);
      assertNotNull("Unable to find MainServiceExtra", service); //$NON-NLS-1$
      
      // remove the service
      javax.wsdl.Service removedService = definition.removeService(serviceQName);
      assertEquals("Incorrect service removed", service, removedService); //$NON-NLS-1$
      
      // make sure service is gone
      javax.wsdl.Service nonexistService = definition.getService(serviceQName);
      assertNull("MainServiceExtra still exists in model", nonexistService); //$NON-NLS-1$
      
      // make sure there is now 1 less service
      assertEquals("Service was not removed (checked via definition.getServices())", totalServices-1, definition.getServices().size()); //$NON-NLS-1$
      assertEquals("Service was not removed (checked via definition.getEServices())", totalServices-1, definition.getEServices().size()); //$NON-NLS-1$
      definitionElement = definition.getElement();
      serviceElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.SERVICE_ELEMENT_TAG);
      assertEquals("Service was not removed (checked via DOM)", totalServices-1, serviceElements.getLength()); //$NON-NLS-1$
      
      // make sure imported service we're going to remove currently exists
      serviceQName = new QName(importedTargetNamespace, "ImportServiceExtra"); //$NON-NLS-1$
      service = definition.getService(serviceQName);
      assertNotNull("Unable to find ImportServiceExtra", service); //$NON-NLS-1$
      
      // attempt to remove the imported service
      removedService = definition.removeService(serviceQName);
      assertNull("ImportServiceExtra was incorrectly removed", removedService); //$NON-NLS-1$
      
      // make sure imported service still exists
      service = definition.getService(serviceQName);
      assertNotNull("ImportServiceExtra no longer exists", service); //$NON-NLS-1$
      
      nonexistService = definition.removeService(new QName(targetNamespace, "doesntexist")); //$NON-NLS-1$
      assertNull("A non-existing service was removed", nonexistService); //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=245263
   */
  public void testRemoveBinding()
  {
    try
    {
      // load a wsdl that imports another wsdl
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/WSDL4JRemove/RemoveViaWSDL4J.wsdl", true); //$NON-NLS-1$
      String targetNamespace = definition.getTargetNamespace();
      String importedTargetNamespace = "http://www.example.org/ImportMe/"; //$NON-NLS-1$
      int totalBindings = 2;
      definition.updateElement();
      
      // make sure wsdl was loaded properly
      assertEquals("Initial bindings were not properly loaded (checked via definition.getBindings())", totalBindings, definition.getBindings().size()); //$NON-NLS-1$
      assertEquals("Initial bindings were not properly loaded (checked via definition.getEBindings())", totalBindings, definition.getEBindings().size()); //$NON-NLS-1$
      Element definitionElement = definition.getElement();
      NodeList bindingElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.BINDING_ELEMENT_TAG);
      assertEquals("Initial bindings were not properly loaded (checked via DOM)", totalBindings, bindingElements.getLength()); //$NON-NLS-1$
      
      // make sure binding we're going to remove currently exists
      QName bindingQName = new QName(targetNamespace, "MainBindingExtra"); //$NON-NLS-1$
      javax.wsdl.Binding binding = definition.getBinding(bindingQName);
      assertNotNull("Unable to find MainBindingExtra", binding); //$NON-NLS-1$
      
      // remove the binding
      javax.wsdl.Binding removedBinding = definition.removeBinding(bindingQName);
      assertEquals("Incorrect binding removed", binding, removedBinding); //$NON-NLS-1$
      
      // make sure binding is gone
      javax.wsdl.Binding nonexistBinding = definition.getBinding(bindingQName);
      assertNull("MainBindingExtra still exists in model", nonexistBinding); //$NON-NLS-1$
      
      // make sure there is now 1 less binding
      assertEquals("Binding was not removed (checked via definition.getBindings())", totalBindings-1, definition.getBindings().size()); //$NON-NLS-1$
      assertEquals("Binding was not removed (checked via definition.getEBindings())", totalBindings-1, definition.getEBindings().size()); //$NON-NLS-1$
      definitionElement = definition.getElement();
      bindingElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.BINDING_ELEMENT_TAG);
      assertEquals("Binding was not removed (checked via DOM)", totalBindings-1, bindingElements.getLength()); //$NON-NLS-1$
      
      // make sure imported binding we're going to remove currently exists
      bindingQName = new QName(importedTargetNamespace, "ImportBindingExtra"); //$NON-NLS-1$
      binding = definition.getBinding(bindingQName);
      assertNotNull("Unable to find ImportBindingExtra", binding); //$NON-NLS-1$
      
      // attempt to remove the imported binding
      removedBinding = definition.removeBinding(bindingQName);
      assertNull("ImportBindingExtra was incorrectly removed", removedBinding); //$NON-NLS-1$
      
      // make sure imported binding still exists
      binding = definition.getBinding(bindingQName);
      assertNotNull("ImportBindingExtra no longer exists", binding); //$NON-NLS-1$
      
      nonexistBinding = definition.removeBinding(new QName(targetNamespace, "doesntexist")); //$NON-NLS-1$
      assertNull("A non-existing binding was removed", nonexistBinding); //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=245263
   */
  public void testRemovePortType()
  {
    try
    {
      // load a wsdl that imports another wsdl
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/WSDL4JRemove/RemoveViaWSDL4J.wsdl", true); //$NON-NLS-1$
      String targetNamespace = definition.getTargetNamespace();
      String importedTargetNamespace = "http://www.example.org/ImportMe/"; //$NON-NLS-1$
      int totalPortTypes = 2;
      definition.updateElement();
      
      // make sure wsdl was loaded properly
      assertEquals("Initial port types were not properly loaded (checked via definition.getPortTypes())", totalPortTypes, definition.getPortTypes().size()); //$NON-NLS-1$
      assertEquals("Initial port types were not properly loaded (checked via definition.getEPortTypes())", totalPortTypes, definition.getEPortTypes().size()); //$NON-NLS-1$
      Element definitionElement = definition.getElement();
      NodeList portTypeElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.PORT_TYPE_ELEMENT_TAG);
      assertEquals("Initial port types were not properly loaded (checked via DOM)", totalPortTypes, portTypeElements.getLength()); //$NON-NLS-1$
      
      // make sure port type we're going to remove currently exists
      QName portTypeQName = new QName(targetNamespace, "MainPortTypeExtra"); //$NON-NLS-1$
      javax.wsdl.PortType portType = definition.getPortType(portTypeQName);
      assertNotNull("Unable to find MainPortTypeExtra", portType); //$NON-NLS-1$
      
      // remove the portType
      javax.wsdl.PortType removedPortType = definition.removePortType(portTypeQName);
      assertEquals("Incorrect portType removed", portType, removedPortType); //$NON-NLS-1$
      
      // make sure portType is gone
      javax.wsdl.PortType nonexistPortType = definition.getPortType(portTypeQName);
      assertNull("MainPortTypeExtra still exists in model", nonexistPortType); //$NON-NLS-1$
      
      // make sure there is now 1 less portType
      assertEquals("PortType was not removed (checked via definition.getPortTypes())", totalPortTypes-1, definition.getPortTypes().size()); //$NON-NLS-1$
      assertEquals("PortType was not removed (checked via definition.getEPortTypes())", totalPortTypes-1, definition.getEPortTypes().size()); //$NON-NLS-1$
      definitionElement = definition.getElement();
      portTypeElements = definitionElement.getElementsByTagNameNS(WSDLConstants.WSDL_NAMESPACE_URI, WSDLConstants.PORT_TYPE_ELEMENT_TAG);
      assertEquals("PortType was not removed (checked via DOM)", totalPortTypes-1, portTypeElements.getLength()); //$NON-NLS-1$
      
      // make sure imported portType we're going to remove currently exists
      portTypeQName = new QName(importedTargetNamespace, "ImportPortTypeExtra"); //$NON-NLS-1$
      portType = definition.getPortType(portTypeQName);
      assertNotNull("Unable to find ImportPortTypeExtra", portType); //$NON-NLS-1$
      
      // attempt to remove the imported portType
      removedPortType = definition.removePortType(portTypeQName);
      assertNull("ImportPortTypeExtra was incorrectly removed", removedPortType); //$NON-NLS-1$
      
      // make sure imported portType still exists
      portType = definition.getPortType(portTypeQName);
      assertNotNull("ImportPortTypeExtra no longer exists", portType); //$NON-NLS-1$
      
      nonexistPortType = definition.removePortType(new QName(targetNamespace, "doesntexist")); //$NON-NLS-1$
      assertNull("A non-existing portType was removed", nonexistPortType); //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * 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();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=247296
   */
  public void testGetWSDLType()
  {
    try
    {
      // load a wsdl
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/GetWSDLType/BadImport.wsdl", true); //$NON-NLS-1$
      definition.updateElement();

      // test all direct child elements of definition to make sure they are expected type
      Element definitionElement = definition.getElement();
      int type = WSDLUtil.getInstance().getWSDLType(definitionElement);
      assertEquals("Definition type incorrectly identified", WSDLConstants.DEFINITION, type);  //$NON-NLS-1$

      NodeList childNodes = definitionElement.getChildNodes();
      Node n = childNodes.item(0);
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Import type incorrectly identified", WSDLConstants.IMPORT, type);  //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("xsd:import type incorrectly identified", -1, type);  //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Types type incorrectly identified", WSDLConstants.TYPES, type); //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Message type incorrectly identified", WSDLConstants.MESSAGE, type); //$NON-NLS-1$
      n = n.getNextSibling();
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Message type incorrectly identified", WSDLConstants.MESSAGE, type); //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Port type type incorrectly identified", WSDLConstants.PORT_TYPE, type); //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Binding type incorrectly identified", WSDLConstants.BINDING, type); //$NON-NLS-1$
      
      n = n.getNextSibling();
      // skip over text node
      if (n.getNodeType() != Node.ELEMENT_NODE)
        n = n.getNextSibling();
      type = WSDLUtil.getInstance().getWSDLType((Element)n);
      assertEquals("Service type incorrectly identified", WSDLConstants.SERVICE, type); //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=247296
   */
  public void testInvalidXSDImports()
  {
    try
    {
      // load a wsdl that contains an xsd:import outside of wsdl:types
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + "samples/BugFixes/GetWSDLType/BadImport.wsdl", true); //$NON-NLS-1$
      
      // there should only be one valid wsdl:import
      Map imports = definition.getImports();
      assertEquals("Incorrect number of imports", 1, imports.size()); //$NON-NLS-1$
      
      // the bad xsd:import should be considered an extensibility element
      List extElements = definition.getExtensibilityElements();
      assertEquals("Incorrect number of extensibility elements", 1, extElements.size());  //$NON-NLS-1$
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }      
  }
  
  /**
   * See https://bugs.eclipse.org/bugs/attachment.cgi?bugid=257279
   */
  public void testReconcileNonWSDLElements()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + 
        "samples/BugFixes/ReconcileNonWSDLElements/ReconcileNonWSDLElements.wsdl", true); //$NON-NLS-1$
            
      Definition newDefinition = WSDLFactory.eINSTANCE.createDefinition();
      assertNotNull("The new definition cannot be null",newDefinition);
      
      // The namespace in the WSDL definition is not instances of WSDLElement, it is an
      // instances of NamespaceImpl
      newDefinition.addNamespace("wsdl", "http://example.org"); //$NON-NLS-1$ //$NON-NLS-2$
      newDefinition.updateElement();
      
      Document newDocument = newDefinition.getDocument();
      assertNotNull("The new definition's document cannot be null",newDocument); //$NON-NLS-1$
      Types types = (Types)definition.getTypes();
      assertNotNull("The definition must have Types",types); //$NON-NLS-1$
      Node typesNode = (types.getElement());
      assertNotNull("The Types element cannot be null",typesNode); //$NON-NLS-1$
      Node toImport = newDocument.importNode(typesNode, true);
      
      // Append child will call org.eclipse.wst.wsdl.internal.impl.WSDLElementImpl.elementContentsChanged(Element)
      // which changes isReconciling to true and calls 
      // org.eclipse.wst.wsdl.internal.impl.WSDLElementImpl.reconcileContents(Element) and changes isReconciling to
      // false after.  However, due to a ClassCast exception in reconcileContents, isReconciling is never changed to
      // false.  The result is newly added WSDL elements not showing up in the EMF model.       
      newDefinition.getElement().appendChild(toImport);
      
      // The bug would have set isReconciling to true and so messages will not be reconciled
      assertNotNull("The definition must have messages",definition.getMessages()); //$NON-NLS-1$
      
      Message messageToAdd = ((Message)definition.getMessage(
        new QName("http://www.example.com/ReconcileNonWSDLElements/","NewOperationRequest"))); //$NON-NLS-1$ //$NON-NLS-2$
      Node messageNode = messageToAdd.getElement();
      assertNotNull("The message to add to the new definition cannot be null",messageNode); //$NON-NLS-1$
      Node toImport2 = newDefinition.getDocument().importNode(messageNode,false);
      
      assertTrue("No messages should exist",newDefinition.getEMessages().size() == 0); //$NON-NLS-1$
      newDefinition.getElement().appendChild(toImport2);
      // The bug causes the message to be added
      assertTrue("A message should have been added", newDefinition.getEMessages().size() == 1); //$NON-NLS-1$      
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }
  }

  /**
   * See https://bugs.eclipse.org/bugs/attachment.cgi?bugid=257279
   */
  public void testReconcilesImportsWithNoLocation()
  {
    try
    {
      Definition definition = DefinitionLoader.load(PLUGIN_ABSOLUTE_PATH + 
        "samples/BugFixes/ReconcilesImportsWithNoLocation/Main.wsdl", true); //$NON-NLS-1$
      assertNotNull(definition);
      String targetNamespace = "http://www.example.org/B/";
      QName serviceQName = new QName(targetNamespace, "B");
      javax.wsdl.Service service = definition.getService(serviceQName);
      assertNotNull(service);
    }
    catch (Exception e)
    {
      e.printStackTrace();
      fail();
    }
  }
}
