/*******************************************************************************
 * Copyright (c) 2002-2005 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 - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.wsi.internal.core.profile.validator.impl.wsdl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.wsdl.Binding;
import javax.wsdl.BindingFault;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Import;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.wsdl.extensions.soap.SOAPFault;
import javax.wsdl.extensions.soap.SOAPHeader;
import javax.wsdl.extensions.soap.SOAPHeaderFault;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.xml.namespace.QName;

import org.eclipse.wst.wsi.internal.core.WSIConstants;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.WSIRuntimeException;
import org.eclipse.wst.wsi.internal.core.analyzer.AnalyzerContext;
import org.eclipse.wst.wsi.internal.core.analyzer.AssertionFailException;
import org.eclipse.wst.wsi.internal.core.analyzer.CandidateInfo;
import org.eclipse.wst.wsi.internal.core.analyzer.ServiceReference;
import org.eclipse.wst.wsi.internal.core.analyzer.config.WSDLElement;
import org.eclipse.wst.wsi.internal.core.profile.ProfileArtifact;
import org.eclipse.wst.wsi.internal.core.profile.TestAssertion;
import org.eclipse.wst.wsi.internal.core.profile.validator.EntryContext;
import org.eclipse.wst.wsi.internal.core.profile.validator.WSDLValidator;
import org.eclipse.wst.wsi.internal.core.profile.validator.impl.BaseValidatorImpl;
import org.eclipse.wst.wsi.internal.core.report.Entry;
import org.eclipse.wst.wsi.internal.core.report.EntryContainer;
import org.eclipse.wst.wsi.internal.core.report.FailureDetail;
import org.eclipse.wst.wsi.internal.core.report.ReportArtifact;
import org.eclipse.wst.wsi.internal.core.report.Reporter;
import org.eclipse.wst.wsi.internal.core.util.EntryType;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLDocument;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLElementList;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLUtils;
import org.eclipse.wst.wsi.internal.core.xml.dom.ElementLocation;
import org.eclipse.wst.wsi.internal.core.xml.schema.TargetNamespaceProcessor;
import org.eclipse.wst.wsi.internal.core.xml.schema.XMLSchemaValidator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;


/**
 * The WSDL validator will verify that the WSDL and associated XML schema definitions
 * are in conformance with the profile.
 *
 * @version 1.0.1
 * @author Peter Brittenham (peterbr@us.ibm.com)
 * @author Graham Turrell 	(gturrell@uk.ibm.com)
 */
public class WSDLValidatorImpl
  extends BaseValidatorImpl
  implements WSDLValidator
{
  /**
   * WSDL URL.
   */
  protected String wsdlURL;

  /**
   * WSDL document.
   */
  protected WSDLDocument wsdlDocument = null;

  /**
   * Entry container map.
   */
  protected HashMap containerMap = new HashMap();

  /* (non-Javadoc)
   * @see org.wsi.test.profile.validator.WSDLValidator#init(org.eclipse.wst.wsi.internal.core.analyzer.AnalyzerContext, org.wsi.test.profile.ProfileArtifact, org.wsi.test.report.ReportArtifact, java.lang.String, org.wsi.wsdl.WSDLDocument, org.wsi.test.report.Reporter)
   */
  public void init(
    AnalyzerContext analyzerContext,
    ProfileArtifact profileArtifact,
    ReportArtifact reportArtifact,
    String wsdlURL,
    WSDLDocument wsdlDocument,
    Reporter reporter)
    throws WSIException
  {
    // BaseValidatorImpl
    super.init(analyzerContext, profileArtifact, reportArtifact, reporter);

    this.wsdlDocument = wsdlDocument;
    if (wsdlDocument != null)
      this.wsdlURL = wsdlDocument.getLocation();

    if (wsdlURL != null)
      this.wsdlURL = wsdlURL;
  }

  /* (non-Javadoc)
   * @see org.wsi.test.profile.validator.WSDLValidator#validate()
   */
  public WSDLDocument validate() throws WSIException
  {
    //WSDLDocument wsdlDocument = null;
    Entry entry = null;

    Service service = null;
    Port port = null;
    Binding binding = null;
    PortType portType = null;
    Operation operation = null;
    Message message = null;

    // it depricated after refactoring 
    // now the inner classes moved out from validator
    //String classPrefix = this.getClass().getName() + "$";
    String classPrefix = this.getClass().getPackage().getName()+".";

    try
    {
      // Validate the WSDL service description
      if (this.wsdlDocument == null)
        this.wsdlDocument = new WSDLDocument(wsdlURL);
    }

    catch (Exception e)
    {
      // ADD: Certain exceptions should result in validation errors

      throw new WSIException(e.getMessage(), e);
    }

    // Get the definition element
    Definition definition = wsdlDocument.getDefinitions();

    // Get service reference from analyzer context
    ServiceReference serviceReference = analyzerContext.getServiceReference();

    // Create normalized data about the service under test.
    CandidateInfo candidate = new CandidateInfo(serviceReference, wsdlDocument);

    analyzerContext.setCandidateInfo(candidate);

    // Set prereq type to entry container
    reporter.setPrereqType(Reporter.PREREQ_TYPE_ENTRY_CONTAINER);

    // always process Import, Definitions & Types assertions 
    // TEMP:
    processDefinitionAssertions(classPrefix, candidate);
    processTypesAssertions(classPrefix, candidate);
    processImportAssertions(classPrefix, candidate);

    // Process the element hierarchy in the WSDL document starting with the one that was specified  
    // FIX: Element finding already completed by CandidateInfo constructor - so use that rather than retest here  

    // ---------------------------
    // wsdl:port
    // ---------------------------
    if (serviceReference.getWSDLElement().isPort())
    {
      // Find the service element
      if ((service =
        definition.getService(
          serviceReference.getWSDLElement().getParentElementQName()))
        == null)
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL service: "
            + serviceReference.getWSDLElement().getParentElementName());
      }

      // Find the port element
      if ((port = service.getPort(serviceReference.getWSDLElement().getName()))
        == null)
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL port: "
            + serviceReference.getWSDLElement().getName());
      }

      // TEMP: Remove until there are port test assertions      
      //processPortAssertions(port, serviceReference, classPrefix, wsdlDocument);	     

      // Next, process the binding
      if (((binding = port.getBinding()) == null) || (binding.isUndefined()))
      {
        //throw new WSIRuntimeException("Could not locate WSDL binding for port: " + port.getName());  
        // Set missingInput for all binding, portType, operation and message test assertions 
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
      }

      else
      {
        processBindingAssertions(
          binding,
          serviceReference,
          classPrefix,
          wsdlDocument);

        // Next, process the portType
        if (((portType = binding.getPortType()) == null)
          || (portType.isUndefined()))
        {
          //throw new WSIRuntimeException("Could not locate WSDL portType for binding: " + binding.getQName().getLocalPart());
          // Set missingInput for all portType, operation and message test assertions 
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
        }

        else
        {
          processMessageAssertions(
            binding,
            serviceReference,
            classPrefix,
            wsdlDocument);
          processPortTypeAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
          processOperationAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
          processMessageAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
        }
      }

    }

    // ---------------------------
    // wsdl:binding
    // ---------------------------
    else if (serviceReference.getWSDLElement().isBinding())
    {
      WSDLElement wsdlElement = serviceReference.getWSDLElement();
      // Find the binding element
      if (wsdlElement.getQName() != null
        && wsdlElement.getQName().getLocalPart() != null
        && wsdlElement.getQName().getLocalPart().length() > 0)
      {
        if (((binding =
          definition.getBinding(serviceReference.getWSDLElement().getQName()))
          == null)
          || (binding.isUndefined()))
        {
          throw new WSIRuntimeException(
            "Could not locate WSDL binding: "
              + serviceReference.getWSDLElement().getName());
        }

        processBindingAssertions(
          binding,
          serviceReference,
          classPrefix,
          wsdlDocument);
        processMessageAssertions(
          binding,
          serviceReference,
          classPrefix,
          wsdlDocument);

        // Next, process the portType
        if (((portType = binding.getPortType()) == null)
          || (portType.isUndefined()))
        {
          //throw new WSIRuntimeException("Could not locate WSDL PortType for Binding: " + binding.getQName().getLocalPart());

          // Set missingInput for all portType, operation and message test assertions 
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
        }

        else
        {
          processPortTypeAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
          processOperationAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);

          // Process each message within each operation of the portType associated with the binding
          processMessageAssertions(
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
        }
      }

      // There was a problem with the binding element specification.  This can 
      // happen when a UDDI tModel did not have a valid binding reference.
      else
      {
        // Set missingInput for all binding, portType, operation and message test assertions 
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
      }
    }

    // ---------------------------
    // wsdl:portType
    // ---------------------------
    else if (serviceReference.getWSDLElement().isPortType())
    {
      // Find the PortType element
      if (((portType =
        definition.getPortType(serviceReference.getWSDLElement().getQName()))
        == null)
        || (portType.isUndefined()))
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL PortType: "
            + serviceReference.getWSDLElement().getName());
      }

      // Set missingInput for all binding test assertions 
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));

      processPortTypeAssertions(
        portType,
        serviceReference,
        classPrefix,
        wsdlDocument);
      processOperationAssertions(
        portType,
        serviceReference,
        classPrefix,
        wsdlDocument);

      // Process each message within each operation of the portType
      processMessageAssertions(
        portType,
        serviceReference,
        classPrefix,
        wsdlDocument);
    }

    // ---------------------------
    // wsdl:operation
    // ---------------------------
    else if (serviceReference.getWSDLElement().isOperation())
    {
      // Find the operation
      // get portType from config parent element
      if (((portType =
        definition.getPortType(
          serviceReference.getWSDLElement().getParentElementQName()))
        == null)
        || (portType.isUndefined()))
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL portType: "
            + serviceReference.getWSDLElement().getParentElementQName());
      }

      if (((operation =
        getOperationFromPortType(
          portType,
          serviceReference.getWSDLElement().getName()))
        == null)
        || (operation.isUndefined()))
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL Operation: "
            + serviceReference.getWSDLElement().getName()
            + "in portType: "
            + portType.getQName());
      }

      // Set missingInput for all binding and portType test assertions 
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));

      processOperationAssertions(
        operation,
        portType,
        serviceReference,
        classPrefix,
        wsdlDocument);
      processMessageAssertions(
        operation,
        serviceReference,
        classPrefix,
        wsdlDocument);
    }

    // ---------------------------
    // wsdl:message
    // ---------------------------
    else if (serviceReference.getWSDLElement().isMessage())
    {
      // Find the message
      if (((message =
        definition.getMessage(serviceReference.getWSDLElement().getQName()))
        == null)
        || (message.isUndefined()))
      {
        throw new WSIRuntimeException(
          "Could not locate WSDL Message: "
            + serviceReference.getWSDLElement().getName());
      }

      // Set missingInput for all binding, portType, and operation test assertions 
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));

      processMessageAssertions(
        message,
        serviceReference,
        classPrefix,
        wsdlDocument);
    }

    else
    {
      throw new WSIRuntimeException(
        "The following WSDL type is not supported: "
          + serviceReference.getWSDLElement().getType());
    }

    // Cleanup
    cleanup();

    // Return WSDL document
    return this.wsdlDocument;
  }

  /**
   * Get entry container using the filename for WSDL document.
   * @param filename a file name.
   * @return entry container using the filename for WSDL document.
   */
  protected EntryContainer getEntryContainer(String filename)
  {
    EntryContainer entryContainer = null;

    // If the entry container already exists, then use it
    if ((entryContainer = (EntryContainer) containerMap.get(filename)) == null)
    {
      // Create new entry container
      entryContainer = this.reporter.createEntryContainer();

      // Set container id using the filename for the WSDL document
      entryContainer.setId(filename);

      // Put the new entry container into the container map
      containerMap.put(filename, entryContainer);
    }

    return entryContainer;
  }

  /**
   * Get operation from port type.
   * @param portType port type.
   * @param operationName operation name.
   * @return operation from port type.
   */
  protected Operation getOperationFromPortType(
    PortType portType,
    String operationName)
  {
    // FIX: wsdl4j available method call below implies that only 
    // name+inputname+outputname uniquely defines operation 
    // Use this instead for now: - get the first operation we find...
    Operation op = null;
    if (portType.getOperations() != null)
    {
      Iterator opIt = portType.getOperations().iterator();

      while (opIt.hasNext())
      {
        op = (Operation) opIt.next();
        if (operationName.equals(op.getName()))
        {
          return op;
        }
      }
    }

    return null; // no matching operation found
  }

  /**
   * Process definition assertions.
   * @param classPrefix class prefix.
   * @param candidate candidate.
   * @throws WSIException if problems occur during processing.
   */
  protected void processDefinitionAssertions(
    String classPrefix,
    CandidateInfo candidate)
    throws WSIException
  {

    Entry entry = null;

    Definition[] wsdlDefinitions = candidate.getDefinitions();

    for (int i = 0; i < wsdlDefinitions.length; i++)
    {
      Definition definition = wsdlDefinitions[i];
      if (definition == null)
        continue;
      // Create entry 
      entry = this.reporter.getReport().createEntry();
      entry.setEntryType(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_DEFINITIONS));
      entry.setReferenceID(definition.getDocumentBaseURI());
      entry.setEntryDetail(definition);

      // Set entry container
      entry.setEntryContainer(
        getEntryContainer(definition.getDocumentBaseURI()));

      // Process all of the definition related test assertions
      processAssertions(
        classPrefix,
        new EntryContext(entry, candidate.getWsdlDocument()));
      // ADD: need to use here the specific document corresponding to the definition??

    }
  }

  /**
   * Process types assertions.
   * @param classPrefix class prefix.
   * @param candidate candidate.
   * @throws WSIException if problem occurs during processing 
   *         type assertions.
   */
  protected void processTypesAssertions(
    String classPrefix,
    CandidateInfo candidate)
    throws WSIException
  {
    Entry entry = null;

    Types[] wsdlTypes = candidate.getTypes();
    Definition[] wsdlDefinitions = candidate.getDefinitions();

    // If there are no types elements, then set all results to missingInput   
    if (wsdlTypes == null || wsdlTypes.length == 0)
    {
      // Set missingInput for all test assertions with this entry type
      setMissingInput(EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_TYPES));
    }

    else
    {
      for (int i = 0; i < wsdlTypes.length; i++)
      {
        Types types = wsdlTypes[i];
        if (types == null)
        {
          // no Types element in i-th document
          continue;
        }

        // Create entry 
        entry = this.reporter.getReport().createEntry();
        entry.setEntryType(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_TYPES));
        entry.setReferenceID(
          candidate.getDefinition(types).getDocumentBaseURI() + "-Types");
        entry.setEntryDetail(types);

        // Set entry container
        entry.setEntryContainer(
          getEntryContainer(wsdlDefinitions[i].getDocumentBaseURI()));

        // Process all of the Types related test assertions
        processAssertions(
          classPrefix,
          new EntryContext(entry, candidate.getWsdlDocument()));
      }
    }
  }

  /**
   * Process import assertions. 
   * @param classPrefix class prefix.
   * @param candidate candidate.
   * @throws WSIException if problem occurs during processing 
   *         import assertions.
   */
  protected void processImportAssertions(
    String classPrefix,
    CandidateInfo candidate)
    throws WSIException
  {

    Entry entry = null;

    Import[] wsdlImports = candidate.getImports();

    // If there are no import elements, then set all results to missingInput   
    if (wsdlImports == null || wsdlImports.length == 0)
    {
      // Set missingInput for all test assertions with this entry type
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_IMPORT));
    }

    else
    {
      for (int i = 0; i < wsdlImports.length; i++)
      {
        Import wsdlImport = wsdlImports[i];
        // Create entry 
        entry = this.reporter.getReport().createEntry();
        entry.setEntryType(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_IMPORT));
        entry.setReferenceID(wsdlImport.getNamespaceURI());
        entry.setEntryDetail(wsdlImport);

        // Set entry container
        entry.setEntryContainer(getEntryContainer(wsdlImport.getLocationURI()));

        // Process all of the import related test assertions
        processAssertions(
          classPrefix,
          new EntryContext(entry, candidate.getWsdlDocument()));
        // ADD: need to use here the specific document corresponding to the import!!
      }
    }
  }

  /**
   * Process port assertions.
   * @param port a port.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         port assertions.
   */
  protected void processPortAssertions(
    Port port,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {
    Entry entry = null;

    // Create entry 	  
    entry = this.reporter.getReport().createEntry();
    entry.setEntryType(EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORT));
    entry.setReferenceID(port.getName());
    entry.setParentElementName(
      serviceReference.getWSDLElement().getParentElementName());
    entry.setEntryDetail(port);

    // Process assertions for this artifact against the target context
    processAssertions(classPrefix, new EntryContext(entry, wsdlDocument));
  }

  /**
   * Process binding assertions.
   * @param binding binding.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         binding assertions.
   */
  protected void processBindingAssertions(
    Binding binding,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {
    Entry entry = null;
    QName bindingQName = binding.getQName();

    // Create entry 
    entry = this.reporter.getReport().createEntry();
    entry.setEntryType(
      EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_BINDING));
    entry.setReferenceID(bindingQName.toString());
    entry.setEntryDetail(binding);

    // Set entry container
    Definition definition =
      analyzerContext.getCandidateInfo().getDefinition(binding);
    entry.setEntryContainer(
      getEntryContainer(
        (definition == null ? null : definition.getDocumentBaseURI())));

    // Process binding test assertions
    processAssertions(classPrefix, new EntryContext(entry, wsdlDocument));
  }

  /**
   * Process port type assertions.
   * @param portType port type.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         port type assertions.
  */
  protected void processPortTypeAssertions(
    PortType portType,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {

    Entry entry = null;
    QName portTypeQName = portType.getQName();

    // Create entry 
    entry = this.reporter.getReport().createEntry();
    entry.setEntryType(
      EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_PORTTYPE));
    entry.setReferenceID(portTypeQName.toString());
    entry.setEntryDetail(portType);

    // Set entry container
    Definition definition =
      analyzerContext.getCandidateInfo().getDefinition(portType);
    entry.setEntryContainer(
      getEntryContainer(
        (definition == null ? null : definition.getDocumentBaseURI())));

    // Process test assertions
    processAssertions(classPrefix, new EntryContext(entry, wsdlDocument));
  }

  /**
   * Process operation assertions.
   * @param operation an operation.
   * @param portType port type.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         operation assertions.
  */
  protected void processOperationAssertions(
    Operation operation,
    PortType portType,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {
    // qualify operation with service location from config.	
    Entry entry = null;

    // Create entry 
    entry = this.reporter.getReport().createEntry();
    entry.setEntryType(
      EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
    entry.setReferenceID(operation.getName());
    entry.setParentElementName(portType.getQName().getLocalPart());
    entry.setEntryDetail(operation);

    // Set entry container
    Definition definition =
      analyzerContext.getCandidateInfo().getDefinition(portType);
    entry.setEntryContainer(
      getEntryContainer(
        (definition == null ? null : definition.getDocumentBaseURI())));

    // Process test assertions
    processAssertions(classPrefix, new EntryContext(entry, wsdlDocument));
  }

  /**
   * Process operation assertions.
   * @param portType port type.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         operation assertions.
   */
  protected void processOperationAssertions(
    PortType portType,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {
    // For each operation, 
    if (portType.getOperations() == null)
    {
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
    }

    else
    {
      Operation operation;
      Iterator opIt = portType.getOperations().iterator();
      while (opIt.hasNext())
      {
        operation = (Operation) opIt.next();
        if (operation == null || operation.isUndefined())
          setMissingInput(
            EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_OPERATION));
        else
          processOperationAssertions(
            operation,
            portType,
            serviceReference,
            classPrefix,
            wsdlDocument);
      }
    }
  }

  /**
   * Process message assertions.
   * @param message a message.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         message assertions.
   */
  protected void processMessageAssertions(
    Message message,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {

    Entry entry = null;
    QName messageQName = message.getQName();

    // Create entry 
    entry = this.reporter.getReport().createEntry();
    entry.setEntryType(
      EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
    entry.setReferenceID(messageQName.toString());
    entry.setEntryDetail(message);

    // Set entry container
    Definition definition =
      analyzerContext.getCandidateInfo().getDefinition(message);
    entry.setEntryContainer(
      getEntryContainer(
        (definition == null ? null : definition.getDocumentBaseURI())));

    // Process binding test assertions
    processAssertions(classPrefix, new EntryContext(entry, wsdlDocument));
  }

  /**
   * Process message assertions.
   * @param binding a binding.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         message assertions.
   */
  protected void processMessageAssertions(
    Binding binding,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {
    HashSet messageSet;

    if (binding.getBindingOperations() != null)
    { // can do nothing if have no operations defined
      messageSet =
        WSDLUtils.findMessages(wsdlDocument.getDefinitions(), binding);

      // Process any messages that were found    
      if (messageSet.size() > 0)
      {
        Iterator messageIt = messageSet.iterator();
        while (messageIt.hasNext())
        {
          Message message = (Message) messageIt.next();
          if (!message.isUndefined())
            processMessageAssertions(
              message,
              serviceReference,
              classPrefix,
              wsdlDocument);
        }
      }
    }
  }

  /**
   * Process message assertions.
   * @param portType port type.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         message assertions.
   */
  protected void processMessageAssertions(
    PortType portType,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {

    HashSet messageSet = new HashSet();

    if (portType.getOperations() != null)
    {
      // can do nothing if have no operations defined

      Iterator opIt = portType.getOperations().iterator();

      while (opIt.hasNext())
      {
        Operation op = (Operation) opIt.next();

        // Since there is no guarantee that we have both and input and output message, 
        // check for its existence before adding it
        if (op.getInput() != null && !op.getInput().getMessage().isUndefined())
          messageSet.add(op.getInput().getMessage());

        if (op.getOutput() != null
          && !op.getOutput().getMessage().isUndefined())
          messageSet.add(op.getOutput().getMessage());

        // also messages from any Faults defined within the operation
        if (op.getFaults() != null)
        {
          Iterator faultIt = op.getFaults().values().iterator();
          Message message;
          while (faultIt.hasNext())
          {
            message = ((Fault) faultIt.next()).getMessage();
            if (!message.isUndefined())
              messageSet.add(message);
          }
        }
      }

      if (messageSet.size() == 0)
      {
        // Set all message test assertion results to missingInput
        setMissingInput(
          EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
      }

      else
      {
        // now step through each derived Message
        Iterator messageIt = messageSet.iterator();
        while (messageIt.hasNext())
        {
          processMessageAssertions(
            (Message) (messageIt.next()),
            serviceReference,
            classPrefix,
            wsdlDocument);
        }
      }
    }
  }

  /**
   * Process message assertions.
   * @param op - operation.
   * @param serviceReference service reference.
   * @param classPrefix class prefix.
   * @param wsdlDocument WSDL document.
   * @throws WSIException if problem occurs during processing 
   *         message assertions.
   */
  protected void processMessageAssertions(
    Operation op,
    ServiceReference serviceReference,
    String classPrefix,
    WSDLDocument wsdlDocument)
    throws WSIException
  {

    HashSet messageSet = new HashSet();
    if (op.getInput() != null && !op.getInput().getMessage().isUndefined())
      messageSet.add(op.getInput().getMessage());

    if (op.getOutput() != null && !op.getOutput().getMessage().isUndefined())
      messageSet.add(op.getOutput().getMessage());

    // also messages from any Faults defined within the operation
    Iterator faultIt = op.getFaults().values().iterator();
    Message message;
    while (faultIt.hasNext())
    {
      message = ((Fault) faultIt.next()).getMessage();
      if (!message.isUndefined())
        messageSet.add(message);
    }

    if (messageSet.size() == 0)
    {
      // Set all message test assertion results to missingInput
      setMissingInput(
        EntryType.getEntryType(EntryType.TYPE_DESCRIPTION_MESSAGE));
    }

    else
    {
      // now step through each derived Message
      Iterator messageIt = messageSet.iterator();
      while (messageIt.hasNext())
      {
        processMessageAssertions(
          (Message) (messageIt.next()),
          serviceReference,
          classPrefix,
          wsdlDocument);
      }
    }
  }

  /* (non-Javadoc)
   * @see org.wsi.test.profile.validator.impl.BaseValidatorImpl#isPrimaryEntryTypeMatch(org.wsi.test.profile.TestAssertion, org.wsi.test.profile.validator.EntryContext)
   */
  protected boolean isPrimaryEntryTypeMatch(
    TestAssertion testAssertion,
    EntryContext targetContext)
  {
    boolean match = false;

    // If the test assertion entry type matches the target context entry type, then contine
    if (testAssertion
      .getEntryTypeName()
      .equals(targetContext.getEntry().getEntryType().getTypeName()))
    {
      match = true;
    }

    return match;
  }

  /* (non-Javadoc)
   * @see org.wsi.test.profile.validator.impl.BaseValidatorImpl#isNotApplicable(org.wsi.test.profile.TestAssertion)
   */
  protected boolean isNotApplicable(TestAssertion testAssertion)
  {
    boolean notApplicable = false;

    // ADD:

    return notApplicable;
  }

  /**
   * Method getSoapFaults.
   * 
   * @param inBinding in binding.
   * @return soap faults.
   * @throws WSIException if problems occur while processing binding faults.
   */
  protected SOAPFault[] getSoapFaults(Binding inBinding) throws WSIException
  {

    Vector soapFaults = new Vector();

    // Go through each bindingFault one at a time
    BindingFault[] bindingFaults = getAllBindingFaults(inBinding);
    for (int fault = 0; fault < bindingFaults.length; fault++)
    {
      SOAPFault soapFault = getSoapFault(bindingFaults[fault]);
      if (soapFault != null)
      {
        soapFaults.add(soapFault);
      }
    }

    SOAPFault[] soapFaultArray = new SOAPFault[soapFaults.size()];
    soapFaults.copyInto(soapFaultArray);

    return soapFaultArray;
  }

  /**
  * Method getAllBindingFaults.
  * 
  * @param inBinding binding.
  * @return all binding faults.
  * @throws WSIException if problems occur during processing.
  */
  protected BindingFault[] getAllBindingFaults(Binding inBinding)
    throws WSIException
  {

    Vector faults = new Vector();

    try
    {

      Iterator bindingOperations = inBinding.getBindingOperations().iterator();

      while (bindingOperations.hasNext())
      {

        try
        {
          BindingOperation bo = (BindingOperation) bindingOperations.next();
          Iterator bindingFaults = bo.getBindingFaults().values().iterator();
          while (bindingFaults.hasNext())
          {

            faults.add((BindingFault) bindingFaults.next());
          }
        }
        catch (NullPointerException e)
        {

        }
      }
    }
    catch (NullPointerException e)
    {
      // no binding operations in this binding - ignore & continue
    }

    BindingFault[] faultArray = new BindingFault[faults.size()];
    faults.copyInto(faultArray);

    return faultArray;
  }

  /**
   * Method getWSDLFaults.
   * 
   * @param bindingFault a binding fault.
   * @return WSDL faults.
   * @throws WSIException if problems occur during processing.
   */
  protected SOAPFault getSoapFault(BindingFault bindingFault)
    throws WSIException
  {

    SOAPFault soapFault = null;
    try
    {
      Iterator faultExtensibles =
        bindingFault.getExtensibilityElements().iterator();

      while (faultExtensibles.hasNext() && soapFault == null)
      {
        try
        {
          soapFault = (SOAPFault) faultExtensibles.next();
        }
        catch (ClassCastException e)
        { // ignore everything but SOAP Fault elements.
        }
      }
    }
    catch (NullPointerException e)
    {
    }

    return soapFault;
  }

  /**
   * Method getSoapHeader.
   * 
   * @param inBinding a binding.
   * @return SOAP headers.
   * @throws WSIException if problems occur during processing.
   */
  protected SOAPHeader[] getSoapHeaders(Binding inBinding) throws WSIException
  {
    // Get all bindings
    Binding[] bindingList = new Binding[1];
    bindingList[0] = inBinding;

    Vector soapHeaderList = new Vector();

    // Go through each binding one at a time
    for (int binding = 0; binding < bindingList.length; binding++)
    {
      try
      {
        // get the list of binding Operations
        BindingOperation[] bindingOperations =
          (BindingOperation[]) bindingList[binding]
            .getBindingOperations()
            .toArray(
            new BindingOperation[0]);

        // get references to the extensible elements within the <input> and <output> elements of this binding <operation>. 
        for (int bo = 0; bo < bindingOperations.length; bo++)
        {

          // Iterate over all input/output extensibles, looking for <SOAP:Body> elements.
          try
          {
            BindingInput bindingInput = bindingOperations[bo].getBindingInput();
            BindingOutput bindingOutput =
              bindingOperations[bo].getBindingOutput();

            Iterator extElements =
              bindingInput.getExtensibilityElements().iterator();
            while (extElements.hasNext())
            {
              try
              {
                soapHeaderList.add((SOAPHeader) extElements.next());
              }
              catch (ClassCastException e)
              { // ignore everything but SOAP Header.
              }
            }

            extElements = bindingOutput.getExtensibilityElements().iterator();
            while (extElements.hasNext())
            {
              try
              {
                soapHeaderList.add((SOAPHeader) extElements.next());
              }
              catch (ClassCastException e)
              { // ignore everything but SOAP Header.
              }
            }
          }
          catch (NullPointerException e)
          { // no extensibility elements for <input> or <output> - ignore : not checking this here.
          }
        }
      }
      catch (NullPointerException e)
      {
        // no binding operations in this binding - ignore & continue
      }
    }

    SOAPHeader[] soapHeaderArray = new SOAPHeader[soapHeaderList.size()];
    soapHeaderList.copyInto(soapHeaderArray);

    return soapHeaderArray;
  }

  /**
   * Method getSoapHeaderFaults.
   * 
   * WSDLDocument getter method - maybe better off in class WSDLDocument...
   * 
   * @param inBinding a binding.
   * @return SOAP header faults.
   * @throws WSIException if problems occur during processing.
   */
  protected SOAPHeaderFault[] getSoapHeaderFaults(Binding inBinding)
    throws WSIException
  {
    Vector soapHeaderFaultList = new Vector();

    // Get the list of SOAP headers
    SOAPHeader[] soapHeaderArray = getSoapHeaders(inBinding);

    // Go through the list and get the header faults
    List list = null;
    for (int header = 0; header < soapHeaderArray.length; header++)
    {
      // Get list for this header
      if ((list = soapHeaderArray[header].getSOAPHeaderFaults()) != null)
      {
        // Add to primary list      
        soapHeaderFaultList.addAll(list);
      }
    }

    SOAPHeaderFault[] soapHeaderFaultArray =
      new SOAPHeaderFault[soapHeaderFaultList.size()];
    soapHeaderFaultList.copyInto(soapHeaderFaultArray);

    return soapHeaderFaultArray;
  }

  /**
   * Method getSoapBodies.
   * 
   * WSDLDocument getter method - maybe better off in class WSDLDocument...
   * 
   * @param inBinding a binding.
   * @return SOAP bodies.
   * @throws WSIException if if problems occur during processing.
   */
  protected SOAPBody[] getSoapBodies(Binding inBinding) throws WSIException
  {
    // REMOVE: Get all bindings
    //Binding[] bindingList = wsdlDocument.getBindings();
    Binding[] bindingList = new Binding[1];
    bindingList[0] = inBinding;

    Vector soapBodies = new Vector();

    // Go through each binding one at a time
    for (int binding = 0; binding < bindingList.length; binding++)
    {
      // get the list of binding Operations
      BindingOperation[] bindingOperations =
        (BindingOperation[]) bindingList[binding]
          .getBindingOperations()
          .toArray(
          new BindingOperation[0]);

      // get references to the extensible elements within the <input> and <output> elements of this binding <operation>. 
      for (int bo = 0; bo < bindingOperations.length; bo++)
      {

        // Iterate over all input/output extensibles, looking for <SOAP:Body> elements.
        try
        {
          Iterator inputExtensibles =
            bindingOperations[bo]
              .getBindingInput()
              .getExtensibilityElements()
              .iterator();
          while (inputExtensibles.hasNext())
          {
            try
            {
              soapBodies.add((SOAPBody) inputExtensibles.next());
            }
            catch (ClassCastException e)
            { // ignore everything but SOAP Body elements.
            }
          }
        }
        catch (NullPointerException e)
        { // no extensibility elements for <input> - ignore : not checking this here.
        }

        try
        {
          Iterator outputExtensibles =
            bindingOperations[bo]
              .getBindingOutput()
              .getExtensibilityElements()
              .iterator();
          while (outputExtensibles.hasNext())
          {
            try
            {
              soapBodies.add((SOAPBody) outputExtensibles.next());
            }
            catch (ClassCastException e)
            { // ignore everything but SOAP Body elements.
            }
          }
        }
        catch (NullPointerException e)
        { // no extensibility elements for <output>.
        }
      }
    }

    SOAPBody[] soapBodyArray = new SOAPBody[soapBodies.size()];
    soapBodies.copyInto(soapBodyArray);

    return soapBodyArray;
  }

  /**
   * Method getSoapBody.
   * 
   * @param bindingInput a BindingInput object.
   * @return  body.
   * @throws WSIException if problems occur during processing.
   */
  protected SOAPBody getSoapBody(BindingInput bindingInput) throws WSIException
  {

    SOAPBody soapBody = null;

    Iterator extensibles = bindingInput.getExtensibilityElements().iterator();
    while (extensibles.hasNext())
    {
      Object extensible = extensibles.next();
      if (extensible instanceof SOAPBody)
      {
        soapBody = (SOAPBody) extensible;
        break;
      }
    }
    return soapBody;
  }

  /**
   * Method getSoapBody.
   * 
   * @param bindingOutput a BindingOutput object.
   * @return SOAP body.
   * @throws WSIException if problems occur during processing.
   */
  protected SOAPBody getSoapBody(BindingOutput bindingOutput)
    throws WSIException
  {

    SOAPBody soapBody = null;

    Iterator extensibles = bindingOutput.getExtensibilityElements().iterator();
    while (extensibles.hasNext())
    {
      Object extensible = extensibles.next();
      if (extensible instanceof SOAPBody)
      {
        soapBody = (SOAPBody) extensible;
        break;
      }
    }
    return soapBody;
  }

  /**
   * Get schema used.
   * @param def definition.
   * @return Schema used.
   * @throws AssertionFailException if problem getting WSDL defintions 
   *         namespace.
   */
  protected String getSchemaUsed(Definition def) throws AssertionFailException
  {
    String schemaUsed = "";

    try
    {
      // Need to read the file directly, since WSDL4J always puts in the default WSDL namespace
      Document document = parseXMLDocumentURL(def.getDocumentBaseURI(), null);

      if (document != null)
      {
        // Get the root element
        Element element = document.getDocumentElement();

        // Get the namespace for this element
        if (element != null)
          schemaUsed = element.getNamespaceURI();
      }
    }

    catch (WSIException we)
    {
      throw new AssertionFailException("problem getting WSDL defintions namespace");
    }

    /*
    // Get the default namespace
    String schemaUsed = def.getNamespace("");
    
    // If the default was set, then process it to get the namespace
    if (schemaUsed == null) {
      // do it the hard way (still better than another DOM parse)... 				
      //WSDLWriter w = new WSDLWriterImpl();
      try {
        WSDLWriter w = WSDLFactory.newInstance().newWSDLWriter();
      	Document doc = w.getDocument(def);
      	Element e = doc.getDocumentElement();
      	schemaUsed = e.getNamespaceURI();
      } 
      catch (NullPointerException e) {
      	throw new AssertionFailException("problem getting WSDL defintions namespace");
      } 
      catch (WSDLException e) {
      	throw new AssertionFailException("problem getting document defintion");
      }      	
    }
    */

    return schemaUsed;
  }

  /**
   * Method getSoapBinding.
   * 
   * Get the SOAP binding for a Binding.
    * 
   * @param binding a binding.
   * @return a SOAP binding.
   * @throws WSIException if problems occur during processing.
   */
  public static SOAPBinding getSoapBinding(Binding binding) throws WSIException
  {
    SOAPBinding soapBinding = null;

    // Get the list of extensibility elements
    List exElements = binding.getExtensibilityElements();
    if (exElements != null)
    {
      Iterator iterator = binding.getExtensibilityElements().iterator();

      //  Check for <soap:binding> element
      while ((iterator.hasNext()) && (soapBinding == null))
      {
        try
        {
          soapBinding = (SOAPBinding) iterator.next();
        }
        catch (ClassCastException e)
        { // ignore everything but SOAP Binding element
        }
      }
    }

    return soapBinding;
  }

  /** 
   * Create XML schema validator.  This is done here because some compilers do not allow
   * the documentList field to be accessed from within an inner class.
   * @param documentBaseURI the base URL.
   * @return newly created XML schema validator.
   */
  protected XMLSchemaValidator createXMLSchemaValidator(String documentBaseURI)
  {
    // Create XML schema validator
    return new XMLSchemaValidator(documentBaseURI, documentList);
  }

  /**
   * Search xsd schema or xsd import from node. If node is xsd import it's loading schema.
   * @param definition a Definition object.
   * @return a list of schema target namespaces.
   * @throws WSIException if problem during processing method.
   */
  protected List getSchemaTargetNamespaceList(Definition definition)
    throws WSIException
  {
    List list = null, nextList = null;

    // Get list of extension elements within the types element
    Types types = null;
    if ((types = definition.getTypes()) != null)
    {
      Iterator iterator = types.getExtensibilityElements().iterator();

      ExtensibilityElement extElement = null;
      while (iterator.hasNext())
      {
        // Get next ext. element
        extElement = (ExtensibilityElement) iterator.next();
        // If this is an unknown ext. element, then see if it is a schema element
        TargetNamespaceProcessor tnsProcessor = null;
        if (extElement instanceof UnknownExtensibilityElement)
        {
          tnsProcessor =
            new TargetNamespaceProcessor(
              definition.getDocumentBaseURI(),
              documentList);

          if ((nextList =
            tnsProcessor.processAllSchema(
              ((UnknownExtensibilityElement) extElement).getElement()))
            != null)
            if (list == null)
              list = new Vector();
          list.addAll(nextList);
        }
      }
    }

    return list;
  }
 /**
   * Search xsd schema or xsd import from node. If node is xsd import it's loading schema.
   * @param definition a Definition object.
   * @return a list of schema target namespaces.
   * @throws WSIException if problem during processing method.
   */
  protected List getSchemaNamespaceList(Definition definition)
    throws WSIException
  {
    List list = new Vector();
    
    // Always add current document targetNamespace
    List targetNamespaceList = getSchemaTargetNamespaceList(definition);
    
    if ((targetNamespaceList != null) && !targetNamespaceList.isEmpty())
      list.addAll(targetNamespaceList);
    
    // Get list of imported WSDL documents
    Map importMap = definition.getImports();

    Import imp;

    // Add each imports targetNamespace to the list
    if (importMap != null && !importMap.isEmpty())
    {
      Iterator values = importMap.values().iterator();
      List importList;
      while (values.hasNext())
      {
        importList = (List) values.next();
        Iterator imports = importList.iterator();
        while (imports.hasNext())
        {
          imp = (Import) imports.next();
          if (imp != null && imp.getDefinition() != null)
          	list.addAll(getSchemaNamespaceList(imp.getDefinition()));
        }
      }
    }

    return list;
  }

  /**
   * Build list of WSDL targetNamespaces.
   * @param definition a Definition object.
   * @return list of WSDL targetNamespaces.
   */
  protected List getWSDLTargetNamespaceList(Definition definition)
  {
    List list = new Vector();

    // Always add current document targetNamespace
    if (definition.getTargetNamespace() != null)
      list.add(definition.getTargetNamespace());

    // Get list of imported WSDL documents
    Map importMap = definition.getImports();

    Import imp;

    // Add each imports targetNamespace to the list
    if (importMap != null && !importMap.isEmpty())
    {
      Iterator values = importMap.values().iterator();
      List importList;
      while (values.hasNext())
      {
        importList = (List) values.next();
        Iterator imports = importList.iterator();
        while (imports.hasNext())
        {
          imp = (Import) imports.next();
          if (imp != null && imp.getDefinition() != null)
          list.addAll(getWSDLTargetNamespaceList(imp.getDefinition()));
            // list.add(imp.getDefinition().getTargetNamespace());
        }
      }
    }

    return list;
  }

  protected class BindingMatch
  {
    private Binding binding;
    private BindingOperation bindingOperation;
    private SOAPBinding soapBinding;
    //private Vector bindingArgs; // set of BindingInputs and BindingOutputs
    private BindingInput bindingInput;
    private BindingOutput bindingOutput;

    // ADD: need to include BindingFault support...
    public BindingMatch(
      Binding b,
      BindingOperation bo,
      SOAPBinding sb,
      BindingInput bin,
      BindingOutput bout)
    {
      binding = b;
      bindingOperation = bo;
      soapBinding = sb;
      //bindingArgs = new Vector();
      //if (bin  != null) { bindingArgs.add(bin);  }
      //if (bout != null) { bindingArgs.add(bout); }
      bindingInput = bin;
      bindingOutput = bout;
    }

    public BindingMatch(
      Binding b,
      BindingOperation bo,
      SOAPBinding sb,
      BindingInput bin)
    {
      this(b, bo, sb, bin, null);
    }

    public BindingMatch(
      Binding b,
      BindingOperation bo,
      SOAPBinding sb,
      BindingOutput bout)
    {
      this(b, bo, sb, null, bout);
    }

    /**
     * Returns the soapBinding.
     * @return SOAPBinding
     */
    public SOAPBinding getSoapBinding()
    {
      return soapBinding;
    }

    /**
     * Returns the bindingOperation.
     * @return BindingOperation
     */
    public BindingOperation getBindingOperation()
    {
      return bindingOperation;
    }

    /**
     * Returns the bindingInput.
     * @return BindingInput
     */
    public BindingInput getBindingInput()
    {
      return bindingInput;
    }

    /**
     * Returns the bindingOutput.
     * @return BindingOutput
     */
    public BindingOutput getBindingOutput()
    {
      return bindingOutput;
    }

    public boolean hasBindingInput()
    {
      return (this.bindingInput != null);
    }

    public boolean hasBindingOutput()
    {
      return (this.bindingOutput != null);
    }

    /**
     * Returns the binding.
     * @return Binding
     */
    public Binding getBinding()
    {
      return binding;
    }

  }

  /**
   * Get binding matches.
  * @param binding a binding.
  * @param soapBindingStyle soap binding style.
  * @param soapBodyUse soap body use.
  * @return binding matches.
  * @throws WSIException if problems occur during processing.
  */
  public BindingMatch[] getBindingMatches(
    Binding binding,
    String soapBindingStyle,
    String soapBodyUse)
    throws WSIException
  {

    Vector bindingMatches = new Vector();

    // Check binding
    SOAPBinding soapBinding = getSoapBinding(binding);

    // check that the soap:binding for this WSDL binding is the specified style
    // ADD: check for null pointer
    if (soapBinding != null)
    {
      String defaultStyle = soapBinding.getStyle();

      if (defaultStyle == null)
      {
        defaultStyle = WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC;
      }

      // Get the set of operations for this WSDL binding
      List bindingOpsList = binding.getBindingOperations();
      if (bindingOpsList != null)
      {
        Iterator bindingOps = bindingOpsList.iterator();
        // for each binding operation:
        while (bindingOps.hasNext())
        {
          BindingOperation bindingOp = (BindingOperation) bindingOps.next();

          SOAPOperation soapOp = getSoapOperation(bindingOp);

          if ((soapOp == null && defaultStyle.equals(soapBindingStyle))
            || (soapOp != null
              && soapOp.getStyle() == null
              && defaultStyle.equals(soapBindingStyle))
            || (soapOp != null
              && soapOp.getStyle() != null
              && soapOp.getStyle().equals(soapBindingStyle)))
          {
            // check binding input & output
            BindingInput bInput = bindingOp.getBindingInput();
            if (bInput != null)
            {
              SOAPBody inputSoapBody = getSoapBody(bInput);
              if (inputSoapBody == null
                || (inputSoapBody.getUse() != null
                  && !inputSoapBody.getUse().equals(soapBodyUse)))
              {
                bInput = null;
              }
            }

            BindingOutput bOutput = bindingOp.getBindingOutput();
            if (bOutput != null)
            {
              SOAPBody outputSoapBody = getSoapBody(bOutput);

              if (outputSoapBody == null
                || (outputSoapBody.getUse() != null
                  && !outputSoapBody.getUse().equals(soapBodyUse)))
              {
                bOutput = null;
              }
            }

            if ((bOutput != null) || (bInput != null))
            {
              // we have a match, add to the vector
              bindingMatches.add(
                new BindingMatch(
                  binding,
                  bindingOp,
                  soapBinding,
                  bInput,
                  bOutput));
            }
          }
        }
      }
    }

    BindingMatch[] BindingMatchArray = new BindingMatch[bindingMatches.size()];
    bindingMatches.copyInto(BindingMatchArray);
    return BindingMatchArray;
  }

  /**
   * Method getSoapOperation.
   *
   * @param bindingOperation a binding operation.
   * @return a soap operation.
   * @throws WSIException if problems while processing.
   */
  public static SOAPOperation getSoapOperation(BindingOperation bindingOperation)
    throws WSIException
  {

    if (bindingOperation.getExtensibilityElements() == null)
    {
      return null;
    }

    Iterator extensibles =
      bindingOperation.getExtensibilityElements().iterator();
    while (extensibles.hasNext())
    {
      Object extensible = extensibles.next();
      if (extensible instanceof SOAPOperation)
      {
        return (SOAPOperation) extensible;
      }
    }
    return null;
  }

  /* 
   * Returns an array of SOAPOperations corresponding to the wsdl:binding supplied.
   */
  protected HashMap getSoapOperations(Binding binding) throws WSIException
  {
    HashMap soapOperationList = new HashMap();

    if (binding.getBindingOperations() == null)
    {
      return null;
    }

    //Vector soapOpVector = new Vector();

    // Get the list of binding operations
    Iterator operations = binding.getBindingOperations().iterator();

    // Check each binding operation to see if it has a soap operation element
    BindingOperation bindingOperation = null;
    while (operations.hasNext())
    {
      bindingOperation = (BindingOperation) operations.next();
      Iterator extensibles =
        bindingOperation.getExtensibilityElements().iterator();
      while (extensibles.hasNext())
      {
        Object extensible = extensibles.next();
        if (extensible instanceof SOAPOperation)
        {
          soapOperationList.put(extensible, bindingOperation.getName());
        }
      }
    }

    //return (SOAPOperation[])soapOpVector.toArray(new SOAPOperation[] {});
    return soapOperationList;
  }

  /**
   * Check part attributes.
   * @param bindingMatch an array of BindingMatch objects.
   * @param inOrOut a String object.
   * @param attrib attribute.
   * @return a boolean.
   * @throws AssertionFailException if the part is not compliant.
   */
  // GT - rework this method with a better way of parameterizing the getters required for the invocation.
  protected boolean checkPartAttributes(
    BindingMatch[] bindingMatch,
    String inOrOut,
    String attrib)
    throws AssertionFailException
  {

    if (!(inOrOut.equals("useInput") || inOrOut.equals("useOutput"))
      || !(attrib.equals("useType") || attrib.equals("useElement")))
    {
      // invalid argument value supplied by calling method - "internal error"
      return false;
    }

    for (int i = 0; i < bindingMatch.length; i++)
    {
      BindingMatch nextMatch = bindingMatch[i];

      // check the associated parts
      Message msg;
      Map parts;
      Iterator partIteration;

      BindingOperation bindingOp = nextMatch.getBindingOperation();
      if (bindingOp == null)
      {
        continue; // no Binding Operation for some reason
      }

      Operation op = bindingOp.getOperation();

      /*	ADD: handle soap:faults in similar way	   		
      try {
      // check faults - remarkably similar.... (need to retain operation id for failuredetail msg)
      	if (nextMatch.hasBindingFault()) {
      				
      		msg = op.getFault().getMessage();
      		parts = msg.getParts();
      				    					     			
      		//check that each part has an element attribute    			
      		partIteration = parts.values().iterator();
      		while (partIteration.hasNext()) {
      			Part part = (Part)partIteration.next();
      			if (part.getElementName() == null) {
      				throw new AssertionFailException("OPERATION: " + op + "MESSAGE: " + msg);
      			}
      		}	 			
      	}
      }
      catch (NullPointerException n) {
      	// no parts found - this qualifies an assertion failure
      	throw new AssertionFailException(n.getMessage());
      }
      */

      try
      {

        QName attributeName;

        //GT: Do we need to check BindingInput / Output here ??

        if (inOrOut.equals("useInput"))
        {
          if (op.getInput() == null || !nextMatch.hasBindingInput())
          {
            // No Input so nothing to check
            continue;
          }

          msg = op.getInput().getMessage();

        }
        else
        { // Looking for Output
          if (op.getOutput() == null || !nextMatch.hasBindingOutput())
          {
            // No Output so nothing to check
            continue;
          }

          msg = op.getOutput().getMessage();
        }

        if (msg == null)
        {
          continue; // nothing to check from this Binding Match (?)
        }

        // Get the list of parts 
        parts = msg.getParts();

        // If there is a parts attribute, then only process those parts
        List partsNameList = null;
        if ((partsNameList = getPartsList(nextMatch, inOrOut)) != null)
        {
          Vector partsList = new Vector();
          Iterator partsNameIterator = partsNameList.iterator();
          while (partsNameIterator.hasNext())
          {
            partsList.add(parts.get((String) partsNameIterator.next()));
          }
          partIteration = partsList.iterator();
        }

        // Otherwise use the complete list of parts
        else
        {
          partIteration = parts.values().iterator();
        }

        //check that each part has an element or type attribute    			
        while (partIteration.hasNext())
        {
          Part part = (Part) partIteration.next();
          if (attrib.equals("useElement"))
          {
            attributeName = part.getElementName();
          }
          else
          { // "useType"
            attributeName = part.getTypeName();
          }

          if (attributeName == null)
          {
            throw new AssertionFailException(
              "Name of operation that failed: "
                + op.getName()
                + "\n"
                + op.toString()
                + "\n"
                + "\nName of message that failed: "
                + msg.getQName()
                + "\n"
                + msg.toString());
          }
        }
      }
      catch (NullPointerException n)
      {
        // no parts found - this qualifies an assertion failure
        throw new AssertionFailException(n.toString());
      }
    }
    return true; // tests successful
  }

  /**
   * Get parts list from a soapbind:body element.
   */
  private List getPartsList(BindingMatch bindingMatch, String type)
  {
    List partsList = null;
    Iterator iterator = null;

    BindingOperation bindingOp;

    try
    {
      // Get the binding operation
      bindingOp = bindingMatch.getBindingOperation();

      // Determine if the binding operation contains a soapbind:body with a parts attribute
      if (type.equals("useInput"))
      {
        iterator =
          bindingOp.getBindingInput().getExtensibilityElements().iterator();
      }
      else
      {
        iterator =
          bindingOp.getBindingOutput().getExtensibilityElements().iterator();
      }
    }
    catch (NullPointerException e)
    {
      return null;
      // either no binding operation, binding input/output, or SOAP element
    }

    // Determine if the binding operation contains a soapbind:body with a parts attribute
    while ((iterator.hasNext()) && (partsList == null))
    {
      try
      {
        SOAPBody soapBody = (SOAPBody) iterator.next();
        partsList = soapBody.getParts();
      }
      catch (ClassCastException cce)
      { // not a SOAPBody extensibility element so ignore
      }
    }

    return partsList;
  }

  /**
   * Get element location.
   * @param wsdlDocument WSDL document.
   * @param wsdlElement WSDL element.
   * @return element location.
   */
  protected ElementLocation getElementLocation(
    WSDLDocument wsdlDocument,
    Object wsdlElement)
  {
    ElementLocation elementLocation = null;
    WSDLElementList wsdlElementList;

    if ((wsdlElementList = wsdlDocument.getElementList()) != null)
    {
      elementLocation = wsdlElementList.getElementLocation(wsdlElement);
    }

    return elementLocation;
  }

  /**
   * Create failure detail.
   * @param message a message.
   * @param entryContext entry context.
   * @return failure detail.
   */
  protected FailureDetail createFailureDetail(
    String message,
    EntryContext entryContext)
  {
    return createFailureDetail(
      message,
      entryContext,
      entryContext.getEntry().getEntryDetail());
  }

  /**
   * Create failure detail.
   * @param message a message.
   * @param entryContext entry context.
   * @param wsdlElement WSDL element.
   * @return failure detail.
   */
  protected FailureDetail createFailureDetail(
    String message,
    EntryContext entryContext,
    Object wsdlElement)
  {
    FailureDetail failureDetail = reporter.createFailureDetail();
    failureDetail.setFailureMessage(message);
    failureDetail.setElementLocation(
      getElementLocation(entryContext.getWSDLDocument(), wsdlElement));
    return failureDetail;
  }

  /** 
   * SOAPBody, SOAPFault, SOAPHeader and SOAPHeaderFault class 
   * interfaces have compatible getUse() and getNamespaceURI() 
   * methods, but wsdl4j does not declare them at the parent interface. 
   * Therefore use reflection to access these common methods.
   * 
   * @param extElement extensibility element.
   * @return true if namespace is found in SOAP literal.
   * @throws NoSuchMethodException if this method cannot be found.
   * @throws InvocationTargetException if problems occur in an invoked method or constructor
   * @throws IllegalAccessException if there is am attempt to load a
   *         class that it does not have access to.
   */
  protected boolean namespaceFoundInSoapLiteral(ExtensibilityElement extElement)
    throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
  {
    Class c = extElement.getClass();
    Method getUseMethod = c.getMethod("getUse", new Class[0]);
    Method getNamespaceURIMethod = c.getMethod("getNamespaceURI", new Class[0]);

    // (use attribute is mandatory but the null case is checked for since a missing use is not
    // checked with this TA. If its missing its invalid but we don't know whether we have doc-lit).     		
    if (getUseMethod.invoke(extElement, null) == null
      || !getUseMethod.invoke(extElement, null).equals(
        WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT))
    {
      return false;
    }

    // return true if namespace found
    boolean namespaceFound =
      (getNamespaceURIMethod.invoke(extElement, null) != null);

    // return true if namespace found
    return namespaceFound;

  }

  /**
   * Verify extensibility element uses literal.
   * @param extensible - extensibility element
   * @return boolean
   * @throws NoSuchMethodException if this method cannot be found.
   * @throws InvocationTargetException if problems occur in an invoked method or constructor
   * @throws IllegalAccessException if there is am attempt to load a
   *         class that it does not have access to.
   */
  protected boolean isLiteral(ExtensibilityElement extensible)
    throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
  {

    Class c = extensible.getClass();
    Method getUseMethod = c.getMethod("getUse", new Class[0]);

    // (use attribute is mandatory but the null case is checked for since a missing use is not
    // checked with this TA. If its missing its invalid but we don't know whether we have doc-lit).     		
    if (getUseMethod.invoke(extensible, null) == null
      || !getUseMethod.invoke(extensible, null).equals(
        WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT))
    {
      return false;
    }

    // return true if shown to have use="literal"
    return true;

  }
}
