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

import java.util.ArrayList;
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.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Message;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.mime.MIMEMultipartRelated;
import javax.wsdl.extensions.mime.MIMEPart;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.wsdl.extensions.soap.SOAPHeader;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.xml.namespace.QName;

import org.apache.xerces.util.URI;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSTypeDefinition;
import org.eclipse.wst.wsi.internal.core.WSIConstants;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.WSITag;
import org.eclipse.wst.wsi.internal.core.analyzer.AnalyzerContext;
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.AnalyzerConfig;
import org.eclipse.wst.wsi.internal.core.document.DocumentFactory;
import org.eclipse.wst.wsi.internal.core.log.Log;
import org.eclipse.wst.wsi.internal.core.log.LogReader;
import org.eclipse.wst.wsi.internal.core.log.MessageEntry;
import org.eclipse.wst.wsi.internal.core.log.MessageEntryHandler;
import org.eclipse.wst.wsi.internal.core.profile.ProfileArtifact;
import org.eclipse.wst.wsi.internal.core.profile.ProfileAssertions;
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.LogValidator;
import org.eclipse.wst.wsi.internal.core.profile.validator.MessageValidator;
import org.eclipse.wst.wsi.internal.core.profile.validator.impl.wsdl.WSDLValidatorImpl;
import org.eclipse.wst.wsi.internal.core.report.ArtifactReference;
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.util.HTTPUtils;
import org.eclipse.wst.wsi.internal.core.util.Utils;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLDocument;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLUtils;
import org.eclipse.wst.wsi.internal.core.xml.XMLUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.ibm.icu.util.StringTokenizer;
import com.ibm.wsdl.Constants;
import com.ibm.wsdl.util.xml.DOM2Writer;
import com.ibm.wsdl.util.xml.DOMUtils;

/**
 * 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 Jim Clune
 * @author Graham Turrell (gturrell@uk.ibm.com)
 * @author Neil Delima (nddelima@ca.ibm.com) 
 */
public abstract class BaseMessageValidator
  extends BaseValidatorImpl
  implements LogValidator
{
  /**
  * WSDL document.
  */
  private WSDLDocument wsdlDocument;

  /**
   * Log entry.
   */
  protected MessageEntry logEntry;
  protected Log log;
  
  private boolean testable;
  private AnalyzerConfig analyzerConfig;

  public void init(AnalyzerContext analyzerContext,
          ProfileAssertions assertions,
          ReportArtifact reportArtifact,
          AnalyzerConfig analyzerConfig,
          Reporter reporter)
          throws WSIException {

      super.init(analyzerContext, assertions.getArtifact(getArtifactType()),
              reportArtifact, reporter);

      testable = analyzerConfig.getLogLocation() != null;
      this.analyzerConfig = analyzerConfig;
      this.wsdlDocument = (WSDLDocument) analyzerContext.getWsdlDocument();
  }

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

    this.analyzerConfig = Utils.getAnalyzerConfig(reporter);
    testable = ((analyzerConfig != null) && (analyzerConfig.getLogLocation() != null));	

    // Save input references
    this.wsdlDocument = wsdlDocument;
  }

  /**
   * Returns wsdlDocument
   * @return wsdlDocument
   */
  public WSDLDocument getWSDLDocument()
  {
    return wsdlDocument;
  }
  /* (non-Javadoc)
   * @see org.wsi.test.profile.validator.MessageValidator#validate(org.wsi.test.profile.validator.EntryContext)
   */
  public void validate(EntryContext entryContext) throws WSIException
  {
    //Entry entry = null;

    // Save log entry to be referenced by other methods
    this.logEntry = entryContext.getMessageEntry();

    // Get reference to the analyzer config object
    AnalyzerConfig analyzerConfig =
      reporter.getReport().getReportContext().getAnalyzer().getAnalyzerConfig();

    /* If Service Description (WSDL/UDDI) NOT supplied in analyzer config OR
     * Service Description IS supplied and the current message correlates to it...
     */
    if ((!analyzerConfig.isWSDLReferenceSet())
      || messageCorrelatesToService(
        entryContext,
        analyzerConfig.getCorrelationType()))
    {
      // now inner classes moved out from the validator
      //String classPrefix = this.getClass().getName() + "$";
      String classPrefix = this.getClass().getPackage().getName()+".";

      // Process assertions for this artifact against the target context
      processAssertions(classPrefix, entryContext);
    }
  }

  /**
   * Check whether the message correlates to the service under test.
   * Use the request part of the request-response pair, from which the correlation of the response is implied.
   * Entities from the Service under test are determined once for all.
   * @param entryContext    an entry context.
   * @param correlationType a correlation type.
   * @return true if the message correlates to the service under test.
   * @throws WSIException if correlation type is not appropriate.
   */
  private boolean messageCorrelatesToService(
    EntryContext entryContext,
    String correlationType)
    throws WSIException
  {

    URI[] endpoints = null;
    boolean correlation = false;

    /* TEMP: Get it from analyzer config passed in on init method
    CandidateInfo candidate = entryContext
                              .getAnalyzerContext()
                              .getCandidateInfo();
    */
    CandidateInfo candidate = analyzerContext.getCandidateInfo();

    // Service reference 
    ServiceReference serviceReference = analyzerContext.getServiceReference();

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

    Binding binding = null;
    if (serviceReference.getWSDLElement().isPort())
    {
      // Get service
      Service service =
        definition.getService(
          serviceReference.getWSDLElement().getParentElementQName());

      // Get port
      Port port = service.getPort(serviceReference.getWSDLElement().getName());

      // Get binding
      binding = port.getBinding();
    }
    else if (serviceReference.getWSDLElement().isBinding())
    {
      // Get binding
      binding =
        definition.getBinding(serviceReference.getWSDLElement().getQName());
    }

    if (binding == null)
    {
      return false;
    }

    if ((endpoints = hostAndPortCorrelation(entryContext)) != null
      && urlPathCorrelation(entryContext, endpoints))
    {

      /* If correlation type is "endpoint", this is all the correlation that can be done.
       * (Note - this is incomplete correlation since >1 service could be associated with the endpoint.
       *  Therefore , if messages for different services on the same endpoint appear in the log file
       *  and correlation type is "endpoint", all those messages will be analyzed).
       */
      if (correlationType
        .equals(WSIConstants.ATTRVAL_CORRELATION_TYPE_ENDPOINT))
      {
        correlation = true;
      }
      else
      {
        // always allow GET requests right through if they've passed Endpoint Correlation
        String requestType = getHttpRequestType(entryContext);
        if ((requestType != null) && requestType.equalsIgnoreCase("GET"))
        {
          correlation = true;
        }
        else
        {
          // The correlationType is not "endpoint" so continue on to processing for at least 
          // "namespace" correlation...

          // get the operation signature (input & output) from request & response messages...	   
          // and do a quick DOM parse 
          Document requestMessage = entryContext.getRequestDocument();

          // Check if namespace is found in request message only
          if (namespaceCorrelation(binding, requestMessage))
          {
            // If namespace found and the correlation type is namespace, then process messages
            if (correlationType
              .equals(WSIConstants.ATTRVAL_CORRELATION_TYPE_NAMESPACE))
            {
              correlation = true;
            }

            // If operation is found and correlation type is operation, then process messages
            else if (
              (operationCorrelation(binding, requestMessage))
                && (correlationType
                  .equals(WSIConstants.ATTRVAL_CORRELATION_TYPE_OPERATION)))
            {
              correlation = true;
            }
            else
            {
              // this should never happen if config schema was followed correctly
              throw new WSIException(
                "Bad correlation type found in config: " + correlationType);
            }
          }
        }
      }
    }

    return correlation;
  }

  /** 
   *  Correlation Check 1: Service Description endpoint vs HTTP Header (test 1)
   *  Check if receiverHostAndPort from request message log matches host & port from WSDL SOAP binding for
   *  the Service under test.
   *  If it does not, stop processing this message pair.
   * @param entryContext an entry context.
   * @return if receiverHostAndPort from request message log matches 
   *         host & port from WSDL SOAP binding for the Service.
   * @throws WSIException if problem occurs during correlation check.
   */
  private URI[] hostAndPortCorrelation(EntryContext entryContext)
    throws WSIException
  {

    // get <receiverHostAndPort> from request message
    String httpHostAndPort = entryContext.getRequest().getReceiverHostAndPort();
    // Search endpoint list for a match with <receiverHostAndPort>

    /* TEMP: Get it from analyzer config passed in on init method
    return entryContext.getAnalyzerContext()
                       .getCandidateInfo()
                       .getEndPoints(httpHostAndPort);
    */
    return analyzerContext.getCandidateInfo().getEndPoints(httpHostAndPort);
  }

  /** 
   * Correlation Check 2: Service Description endpoint vs HTTP Header (test 2)
   * 
   * Use analyzer config host & port, plus URL path (from request message header HTTP POST)
   * to look for the corresponding endpoint in the Service Definition.
   * If it does not, stop processing this message pair.
   * @param entryContext an entry context.
   * @param endpoints an array of endpoints.
   * @return true if corresponding endpoints are found in the Service Definition.
   * @throws WSIException if problem occurs during correlation check.
   */
  private boolean urlPathCorrelation(
    EntryContext entryContext,
    URI[] endpoints)
    throws WSIException
  {

    // compares: protocol (must be http for POST), host, port and path.

    // get POST URI path from message using Tokenizer	
    Vector requestLine =
      getHttpRequest(entryContext.getRequest().getHTTPHeaders());
    if (requestLine == null)
    {
      return false; // an unexpected HTTP request type !
    }

    String requestPath = (String) requestLine.get(1);
    // Path immediately follows POST

    // compare path with those in the previous generated URI list	
    Vector filteredEndpoints = new Vector();
    for (int i = 0; i < endpoints.length; i++)
    {
      if (endpoints[i].toString().endsWith(requestPath))
      {
        filteredEndpoints.add(endpoints[i]);
      }
    }

    if (filteredEndpoints.size() == 0)
      return false;

    // this URI should be unique in the WSDL - there should be at most one match
    // but if we have at least one, that's sufficient to accept the message

    return true;
  }

  /** 
   * Correlation Check 3: Service Description namespace.
   * 
   * Determine if the Service Description declares the namespace that appears in the (request?) message soap body.
   * Location of relevent namespace :
   * Operation type                    	- Message Namespace: (compare with)  Service Definition Namespace:
   * (from message? endpoint? where?)
   * rpc-literal                           &lt;soap:Body&gt; child namespace.        &lt;soapbind:body&gt; namespace.
   * doc-literal			                 &lt;soap:Body&gt; child namespace.       targetNameSpace of schema that
   *                                                                          defines  &lt;soap:body&gt; child.
   * If it doesn't match, stop processing this message pair.
   * @param binding a binding.
   * @param request a request.
   * @return true if description declared in the description are the 
   *         same as those that appear in the message soap body.
   * @throws WSIException if problem occurs during correlationcheck.                                                                       
   */
  private boolean namespaceCorrelation(Binding binding, Document request)
    throws WSIException
  {
    boolean namespaceFound = false;
    String bindingStyle = WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC;

    // Get operation namespace from the request soap message
    String soapOpNS = getSoapBodyChild(request).getNamespaceURI();

    // Get soapbind:binding
    SOAPBinding soapBinding = null;
    if ((soapBinding = WSDLUtils.getSoapBinding(binding)) != null)
    {
      bindingStyle = soapBinding.getStyle();
    }

    // Go through each operation in the binding and check for namespace match
    Iterator operations = binding.getBindingOperations().iterator();
    while (operations.hasNext() && !(namespaceFound))
    {
      BindingOperation bindingOperation = (BindingOperation) operations.next();

      // If rpc-literal, then look at namespace attribute on soapbind:body
      if (WSDLUtils.isRpcLiteral(bindingStyle, bindingOperation))
      {
        // Get soapbind:body element 
        SOAPBody soapBody = WSDLUtils.getInputSoapBody(bindingOperation);

        if ((soapBody.getNamespaceURI() != null)
          && (soapBody.getNamespaceURI().equals(soapOpNS)))
        {
          namespaceFound = true;
        }
      }

      // If doc-literal, then check namespace
      else if (WSDLUtils.isDocLiteral(bindingStyle, bindingOperation))
      {
        int partCount;
        Iterator partsIterator = null;

        // Get first part name from soapbind:body element parts attribute
        String partName = getFirstPartName(bindingOperation);

        // Get the list of parts from the message           
        Map partsMap = null;
        if ((partsMap =
          bindingOperation.getOperation().getInput().getMessage().getParts())
          != null)
        {
          partsIterator = partsMap.values().iterator();

          // If the part name wasn't specified on the soapbind:body element, then process just the first one
          if (partName == null)
            partCount = 1;
          else
            partCount = partsMap.size();

          for (int i = 0; i < partCount && !namespaceFound; i++)
          {
            // Get next part
            Part part = (Part) partsIterator.next();

            // If part name matches or there is no part name, then check namespace
            if ((partName == null)
              || ((partName != null) && (part.getName().equals(partName))))
            {
              if ((part.getElementName().getNamespaceURI() != null)
                && (part.getElementName().getNamespaceURI().equals(soapOpNS)))
              {
                namespaceFound = true;
              }
            }
          }
        }
      }
    }

    return namespaceFound;
  }

  /** 
  * Correlation Check 4 : Service Description "operation"
  *
  * Check if the message content matches any of the candidate operation definitions 
  * for request and response in the Service Description.
  *  
  * For both request and response, look for the soap body child element name
  * in the list of candidate operation names.
  * @param binding        a binding.
  * @param requestMessage a request message.
  * @return true if the message content matches any of the candidate 
  *         operation definitions for request and response in the 
  *         Service Description.
  * @throws WSIException if problem occurs during correlationcheck.
  */
  private boolean operationCorrelation(
    Binding binding,
    Document requestMessage)
    throws WSIException
  {
    boolean operationFound = false;

    String bindingStyle = WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC;

    // Get soapbind:binding
    SOAPBinding soapBinding = null;
    if ((soapBinding = WSDLUtils.getSoapBinding(binding)) != null)
    {
      bindingStyle = soapBinding.getStyle();
    }

    // Get the first child element from the soap body
    Element soapBodyChild = getSoapBodyChild(requestMessage);

    // If there is a child element, then check it
    if (soapBodyChild != null)
    {
      // Get operation name from the soap:body
      String operationName = soapBodyChild.getLocalName();

      // Get operation QName
      QName operationQName =
        new QName(soapBodyChild.getNamespaceURI(), operationName);

      // Go through each operation in the binding and check for namespace match
      Iterator operations = binding.getBindingOperations().iterator();
      while (operations.hasNext() && !(operationFound))
      {
        BindingOperation bindingOperation =
          (BindingOperation) operations.next();

        // If rpc-literal, then look at namespace attribute on soapbind:body
        if (WSDLUtils.isRpcLiteral(bindingStyle, bindingOperation))
        {
          // Get soapbind:body element 
          if (bindingOperation.getName().equals(operationName))
            operationFound = true;
        }

        // If doc-literal, then check namespace
        else if (WSDLUtils.isDocLiteral(bindingStyle, bindingOperation))
        {
          int partCount;
          Iterator partsIterator = null;

          // Get first part name from soapbind:body element parts attribute
          String partName = getFirstPartName(bindingOperation);

          // Get the list of parts from the message           
          Map partsMap = null;
          if ((partsMap =
            bindingOperation.getOperation().getInput().getMessage().getParts())
            != null)
          {
            partsIterator = partsMap.values().iterator();

            // If the part name wasn't specified on the soapbind:body element, then process just the first one
            if (partName == null)
              partCount = 1;
            else
              partCount = partsMap.size();

            for (int i = 0; i < partCount && !operationFound; i++)
            {
              // Get next part
              Part part = (Part) partsIterator.next();

              // If part name matches or there is no part name, then check namespace
              if ((partName == null)
                || ((partName != null) && (part.getName().equals(partName))))
              {
                if ((part.getElementName() != null)
                  && (part.getElementName().equals(operationQName)))
                {
                  operationFound = true;
                }
              }
            }
          }
        }
      }
    }

    // Go through each operation to find a match
    return operationFound;
  }

  /**
   * Create failure detail.
   * @param message       a message.
   * @param entryContext  an entry context.
   * @return failure detail.
   */
  public FailureDetail createFailureDetail(
    String message,
    EntryContext entryContext)
  {
    FailureDetail failureDetail = reporter.createFailureDetail();
    failureDetail.setFailureMessage(message);
    failureDetail.setElementLocation(
      entryContext.getMessageEntry().getElementLocation());
    return failureDetail;
  }

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

    // If the additional entry is not available, then set notApplicable
    if (testAssertion.getAdditionalEntryTypeList().getWSDLInput() != null
      && !testAssertion.getAdditionalEntryTypeList().getWSDLInput().equals("none")
      && analyzerContext.getServiceReference().getWSDLLocation() == null)
    {
      notApplicable = true;
    }

    return notApplicable;
  }


  /**
   * Get POST request.
   * @param httpHeader an HTTP 
   * @return POST request.
   */
  public Vector getPostRequest(String httpHeader)
  {
    //Request-Line   = Method SP Request-URI SP HTTP-Version CRLF
    Vector requestLine = new Vector();
    String startLine = null;

    StringTokenizer httpMessageTokenizer =
      new StringTokenizer(httpHeader, "\n\r\f");

    if (httpMessageTokenizer.hasMoreTokens())
    {
      startLine = httpMessageTokenizer.nextToken();
    }

    if (startLine.startsWith("POST"))
    {
      StringTokenizer startLineTokenizer =
        new StringTokenizer(startLine, "\u0020");
      while (startLineTokenizer.hasMoreTokens())
      {
        requestLine.add(startLineTokenizer.nextToken());
      }
    }
    return requestLine;
  }

  /**
   * Get HTTP request.
   * @param httpHeader an HTTP 
   * @return HTTP request.
  */
  private Vector getHttpRequest(String httpHeader)
  {
    //Request-Line   = Method SP Request-URI SP HTTP-Version CRLF
    Vector requestLine = new Vector();
    String startLine = null;

    StringTokenizer httpMessageTokenizer =
      new StringTokenizer(httpHeader, "\n\r\f");

    if (httpMessageTokenizer.hasMoreTokens())
    {
      startLine = httpMessageTokenizer.nextToken();
    }

    if (startLine.startsWith("POST") || startLine.startsWith("GET"))
    {
      StringTokenizer startLineTokenizer =
        new StringTokenizer(startLine, "\u0020");
      while (startLineTokenizer.hasMoreTokens())
      {
        requestLine.add(startLineTokenizer.nextToken());
      }
    }
    else
    {
      requestLine = null; // signify not POST or GET
    }

    return requestLine;
  }

  /**
   * Get HTTP request type.
   * @param entryContext an entry context.
   * @return HTTP request type.
   */
  private String getHttpRequestType(EntryContext entryContext)
  {
    //Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

    String httpHeader = entryContext.getRequest().getHTTPHeaders();
    String httpRequestType = null;
    String startLine = null;

    StringTokenizer httpMessageTokenizer =
      new StringTokenizer(httpHeader, "\n\r\f");

    if (httpMessageTokenizer.hasMoreTokens())
    {
      startLine = httpMessageTokenizer.nextToken();
      StringTokenizer startLineTokenizer =
        new StringTokenizer(startLine, "\u0020");
      if (startLineTokenizer.hasMoreTokens())
      {
        httpRequestType = startLineTokenizer.nextToken();
      }
    }
    return httpRequestType;
  }

  /**
   * Determine if the message is a response for a one-way operation.
   * @param entryContext an entry context.
   * @return true if the message is a response for a one-way operation.
   */
  public boolean isOneWayResponse(EntryContext entryContext)
  {
    boolean oneway = false;

    // TEMP: If this is a response message and there is no content, then set one-way to true
    // TEMP: Need to find a way to determine if the response is for a one-way message
    if (entryContext
      .getMessageEntry()
      .getType()
      .equalsIgnoreCase(MessageEntry.TYPE_RESPONSE)
      && entryContext.getMessageEntry().getMessage().length() == 0)
    {
      oneway = true;
    }

    return oneway;
  }

  /**
   * messageIsDocLitSchemaValid.
   *
   * Validates the doc-lit messages against the schema found in a candidate wsdl document.
   *
   * Identify (or be given) a reference in the wsdl to elements (found in &lt;wsdl:types&gt;&lt;schema&gt;...)
   * that are immediate children elements in the soap body.
   * @param entryContext an entry context.
   * @return true if the document literal message is compliant to the 
   *         schema found in a candidate WSDL document.
   * @throws WSIException if there is a parsing problem during validation.
   */
  public boolean messageIsDocLitSchemaValid(EntryContext entryContext)
    throws WSIException
  {

    // This method should use a validating parser that is capable of acceppting multiple schema references
    // programmatically. Then, every schema in candidate wsdl can be passed in to the validator. This avoids the
    // need to pinpoint a particular schema element from all candidate wsdl:types, corresponding to the 
    // wsdl:operation being used. The pinpointing is an incomplete workaround for parsers not capable 
    // of accepting arrays of scehma references 
    // [ i.e. the DOM factory.setAttribute(JAXP_SCHEMA SOURCE, Object[] {...}) ]
    // get all xs:schema from all candidate wsdl:types                    
    // add each <schema> to an array and pass this array to the validating parser
    // when validating the/each soap body child.

    // use the referenced WSDL file and its imported files to find schemas
    List schemaWSDLs = new ArrayList();
    List inlineSchemas = new ArrayList();
    List schemaStrings = new ArrayList();

    Definition[] allDefs =
      analyzerContext.getCandidateInfo().getDefinitions();
    for (int thisDef = 0; thisDef < allDefs.length; thisDef++)
    {
      schemaWSDLs.add(allDefs[thisDef].getDocumentBaseURI());
    }
    Iterator fileIterator = schemaWSDLs.iterator();
    while (fileIterator.hasNext())
    {
      // parse file if possible
      Document wsdlDoc = null;
      String wsdlURI = (String) fileIterator.next();
      try
      {
        wsdlDoc = XMLUtils.parseXMLDocumentURL(wsdlURI, null);
      }
      catch (Exception e)
      {
        continue;
      }
      Element root = wsdlDoc.getDocumentElement();
      // find the schema
      NodeList schemaElements = root.getElementsByTagNameNS(
        WSITag.ELEM_XSD_SCHEMA.getNamespaceURI(),
        WSITag.ELEM_XSD_SCHEMA.getLocalPart());

      for (int elem = 0; elem < schemaElements.getLength(); elem++)
      {     
        Element schema = (Element) schemaElements.item(elem);
        // copying all the NS declarations from wsdl:definitions wsdl:types
        copyNSDeclarations(root, schema);
        copyNSDeclarations((Element) schema.getParentNode(), schema);
        // Replacing all relative schemaLocation URIs with absolute ones
        replaceRelativeURIs(schema, wsdlURI);
        inlineSchemas.add(schema);
      }
    }

    // Note that the Xerces parser ONLY accepts an array
    // of schemas with unique namespaces.
    if (!duplicateNamespacesDetected(inlineSchemas))
    {
      // Serialize the schema elements inside the Types, then use this as
      // the schema string for the validation
      Iterator i = inlineSchemas.iterator();
      while (i.hasNext())
      {
    	Element schema = (Element)i.next(); 
        String schemaString = DOM2Writer.nodeToString(schema);
        schemaStrings.add(schemaString);
      }

      NodeList elementList = entryContext.getMessageEntryDocument()
        .getElementsByTagNameNS(WSITag.ELEM_SOAP_BODY.getNamespaceURI(),
            WSITag.ELEM_SOAP_BODY.getLocalPart());
      if (elementList == null || elementList.getLength() != 1)
      {
        // should only be a single soap body !
        return false; // probably an error condition though
      }

      NodeList soapBodyChildList = ((Element)elementList.item(0)).getChildNodes();
      for (int child = 0; child < soapBodyChildList.getLength(); child++)
      {
        Node soapBodyChild = soapBodyChildList.item(child);
        if (soapBodyChild.getNodeType() == Node.ELEMENT_NODE)
        {
          // do all for now
          try
          {
            // Write out element tree to String
            String messageContent = DOM2Writer.nodeToString(soapBodyChild);
            // parse the child element, validating against the schema 
            XMLUtils.parseXML(messageContent, schemaStrings);
          }
          catch (WSIException e)
          {
            if (e.getTargetException() instanceof SAXException)
            {
              // validation failed
              throw new WSIException(e.getTargetException().getMessage());
            }
            throw e;
          }
          catch (Exception e)
          {
            throw new WSIException("Validating Parsing problem", e);
            // Bad things have happened
          }
        }
      }   
    }
    return true;
  }

  /**
   * Copy the namespace declarations.
   * @param parent a message.
   * @param child a stripped message.
   */
  private void copyNSDeclarations(Element parent, Element child)
  {
    NamedNodeMap nodeMap = parent.getAttributes();
    for (int nodeId = 0; nodeId < nodeMap.getLength(); nodeId++)
    {
      Node node = nodeMap.item(nodeId);

      if ((node.getNodeType() == Node.ATTRIBUTE_NODE)
        && (node.getNodeName().startsWith("xmlns:")))
      {
        String nodeName = node.getNodeName();
        // If an NS being copied is not the same as the child element has, copy it
        if (!child.getNodeName().startsWith(
          nodeName.substring(nodeName.indexOf(":") + 1) + ":"))
        {
          child.setAttribute(nodeName, node.getNodeValue());
        }
      }
    }
  }

  /**
   * Replaces all relative URIs for schemaLocation attributes.
   * @param schema an xsd:schema element.
   * @param wsdlURI an URI of WSDL that contains xsd:schema being processed.
   */
  private void replaceRelativeURIs(Element schema, String wsdlURI)
  {
    // Retrieving all xsd:import elements
    NodeList imports = schema.getElementsByTagNameNS(
      WSITag.ELEM_XSD_IMPORT.getNamespaceURI(),
      WSITag.ELEM_XSD_IMPORT.getLocalPart());
    // Going through the elements
    for (int i = 0; i < imports.getLength(); i++)
    {
      Element imp = (Element) imports.item(i);
      // Getting the schemaLocation attribute
      Attr schemaLocation =
        XMLUtils.getAttribute(imp, WSITag.ATTR_XSD_SCHEMALOCATION);
      // If the attribute is present
      if (schemaLocation != null)
      {
        // Trying to create an URI object using attribute's value
        URI uri = null;
        try
        {
          uri = new URI(schemaLocation.getValue());
        }
        catch (Exception e) {}
        // If the value is not an absolute URI (the URI constructor throws the
        // MalformedURIException), creating the absolute URI using wsdlURI
        if (uri == null)
        {
          String newURI = wsdlURI.substring(0, wsdlURI.lastIndexOf("/") + 1)
            + schemaLocation.getValue();
          try
          {
            uri = new URI(newURI);
            // Setting a new URI as a value for the schemaLocation attribute
            schemaLocation.setValue(uri.toString());
          }
          catch (Exception e) {}
        }
      }
    }
  }

  /**
   * Returns binding operation matched for SOAP message.
   * @param entryType message entry type.
   * @param doc a message.
   * @return any binding operation matched, null if it is not found.
   */
  public BindingOperation getOperationMatch(EntryType entryType, Document doc) 
  {
    BindingOperation bindingOperation = null;
    try
    {
      // Getting the name of the first SOAP Body child element
      QName operation = getOperationFromMessage(doc);
      if (operation != null)
      {
        // Retrieving all the RPC binding operations from wsdl:binding
        BindingOperation[] rpcBindingOps = getMatchingBindingOps(
          WSIConstants.ATTRVAL_SOAP_BIND_STYLE_RPC,
          analyzerContext.getCandidateInfo().getBindings());
        // Retrieving binding operation by the given operation name
        bindingOperation = getOperationMatch(
          entryType, operation, rpcBindingOps);
        // If no one RPC operation matched
        if(bindingOperation == null)
        {
          // Retrieving all the document binding operations from wsdl:binding
          BindingOperation[] docBindingOperations = getMatchingBindingOps(
            WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC,
            analyzerContext.getCandidateInfo().getBindings());
          // Retrieving binding operation by given element name
          BindingOperation[] potentialDocLitOps =
            getDocLitOperations(entryType, operation, docBindingOperations);
          // If there is exactly one operation matched
          if (potentialDocLitOps.length == 1)
            bindingOperation = potentialDocLitOps[0];
        }
      }
    }
    catch (Exception e) {}

    return bindingOperation;
  }

  /**
   * Match either Input or Output.
   * @param messageEntryType message entry type.
   * @param soapMessage soap message.
   * @param op binding operations.
   * @return matched operation.
   */
  public BindingOperation getOperationMatch(
    EntryType messageEntryType,
    Document soapMessage,
    BindingOperation[] op)
  {
    // Get operation from message
    QName operation = getOperationFromMessage(soapMessage);
    // list of QNames

    return getOperationMatch(messageEntryType, operation, op);
  }

  /**
   * Match either Input or Output.
   * @param messageEntryType message entry type.
   * @param operation SOAP operation name.
   * @param op binding operations.
   * @return matched operation.
   */
  public BindingOperation getOperationMatch(
    EntryType messageEntryType,
    QName operation,
    BindingOperation[] op)
  {
    QName checkOperation;

    // Look for a candidate operation in the wsdl that matches this signature.
    for (int k = 0; k < op.length; k++)
    {
      String name = null;
      List extensibles = null;
      BindingOperation bindingOp = op[k];

      if (messageEntryType.isType(MessageValidator.TYPE_MESSAGE_REQUEST)
        && (bindingOp.getOperation().getInput() != null))
      {
        name = bindingOp.getOperation().getName();
        extensibles = bindingOp.getBindingInput().getExtensibilityElements();
      }
      else if (
        messageEntryType.isType(MessageValidator.TYPE_MESSAGE_RESPONSE)
          && (bindingOp.getOperation().getOutput() != null))
      {
        name = bindingOp.getOperation().getName() + "Response";
        extensibles = bindingOp.getBindingOutput().getExtensibilityElements();
      }

      // Get soap:body
      SOAPBody soapBody = getSoapBody(extensibles);
      if (soapBody == null)
        checkOperation = new QName(name);
      else
        checkOperation = new QName(soapBody.getNamespaceURI(), name);

      if (operation != null && operation.equals(checkOperation))
      {
        return (bindingOp);
      }
    }
    return null;
  }

  /**
   * Match either Input or Output.
   * @param messageEntryType a message entry type.
   * @param soapMessage a soap message.
   * @param op binsing operations.
   * @return matched operation.
   */
  public BindingOperation getOperationPartsMatch(
    EntryType messageEntryType,
    Document soapMessage,
    BindingOperation[] op)
  {
    Map parts = getPartListFromMessage(soapMessage); // list of QNames

    // Look for a candidate operation in the wsdl that matches this signature.
    for (int k = 0; k < op.length; k++)
    {

      Message wsdlMessage = null;
      List extensibles = null;
      BindingOperation bindingOp = op[k];

      if (messageEntryType.isType(MessageValidator.TYPE_MESSAGE_REQUEST)
        && (bindingOp.getOperation().getInput() != null))
      {
        wsdlMessage = bindingOp.getOperation().getInput().getMessage();
        extensibles = bindingOp.getBindingInput().getExtensibilityElements();
      }
      else if (
        messageEntryType.isType(MessageValidator.TYPE_MESSAGE_RESPONSE)
          && (bindingOp.getOperation().getOutput() != null))
      {
        wsdlMessage = bindingOp.getOperation().getOutput().getMessage();
        extensibles = bindingOp.getBindingOutput().getExtensibilityElements();
      }
      //wsdlFaultParts = op[k].getFaults();
      // ADD: check for case when response message is a fault

      if (sameParts(parts, wsdlMessage, getSoapHeader(extensibles)))
      {
        return (bindingOp);
      }
    }
    return null;
  }

  /** 
   * BindingOperation getOperationPartsMatch(..).
   * 
   * Find one or more matching binding operations from the WSDL corresponding to the
   * given request-response signature.
   * 
   * This overloaded version is intended for possible Correlation only (not assertions),
   * since it checks for an operation signature on a request-response pair.
   * Assertions now check request & response messages independently. 
   * @param requestMessage a request message.
   * @param responseMessage a response message.
   * @param op binding operations.
   * @return matched operation.
   */
  //private BindingOperation getOperationPartsMatch(
  //  Document requestMessage,
  //  Document responseMessage,
  //  BindingOperation[] op)
  //{
  //  Map inParts = getPartListFromMessage(requestMessage); // list of QNames
  //  Map outParts = getPartListFromMessage(responseMessage);
  //  // list of QNames
  //
  //  // Look for a candidate operation in the wsdl that matches this signature.
  //  for (int k = 0; k < op.length; k++)
  //  {
  //
  //    //Map wsdlFaultParts = null;
  //    Message wsdlInMessage = null;
  //    Message wsdlOutMessage = null;
  //
  //    BindingOperation bindingOp = op[k];
  //    if (bindingOp.getOperation().getInput() != null)
  //    {
  //      wsdlInMessage = bindingOp.getOperation().getInput().getMessage();
  //    }
  //
  //    if (bindingOp.getOperation().getOutput() != null)
  //    {
  //      wsdlOutMessage = bindingOp.getOperation().getOutput().getMessage();
  //    }
  //    //wsdlFaultParts = op[k].getFaults();
  //    // ADD: check for case when response message is a fault
  //
  //    if (sameParts(inParts,
  //      wsdlInMessage,
  //      getSoapHeader(bindingOp.getBindingInput().getExtensibilityElements())))
  //    {
  //      // match on the request - now check response if its not a fault
  //      if (responseMessage != null && isFault(responseMessage))
  //      {
  //        return (bindingOp);
  //      }
  //      else if (
  //        sameParts(
  //          outParts,
  //          wsdlOutMessage,
  //          getSoapHeader(
  //            bindingOp.getBindingOutput().getExtensibilityElements())))
  //      {
  //        // It does match so treat this as a relevant message pair. 
  //        // Let the message through for validation.
  //        //ADD: could pass the operations list back to the entryContext for the message.
  //        return (bindingOp);
  //      }
  //    }
  //  }
  //  return null;
  //}

  /**
   * Get the soap:body from a List of extensibility elements.
   * @param extElems a list of extensibility elements.
   * @return the soap:body from a List of extensibility elements.
   */
  private SOAPBody getSoapBody(List extElems)
  {
    // Find the soap body
    if (extElems != null)
    {
      for (int i = 0; i < extElems.size(); i++)
      {
        ExtensibilityElement extElem = (ExtensibilityElement) extElems.get(i);
        if (extElem.getElementType().equals(WSITag.WSDL_SOAP_BODY))
        {
          return (SOAPBody) extElem;
        }
        // If the element is mime:multipartRelated
        else if (extElem.getElementType().equals(WSITag.WSDL_MIME_MULTIPART))
        {
          // Getting the mime:part elements of the mime:multipartRelated
          List mimeParts = ((MIMEMultipartRelated) extElem).getMIMEParts();
          // Going through all the mime:part elements
          for (int j = 0; j < mimeParts.size(); j++)
          {
            // Collecting all the mime:content elements of this mime:part
            SOAPBody soapBody = getSoapBody(
              ((MIMEPart) mimeParts.get(j)).getExtensibilityElements());
            if (soapBody != null)
              return soapBody;
          }
        }
      }
    }

    return null;
  }

  /**
   * Get the SOAPHeader from a List of extensibility elements.
   * @param extensibles a list of extensibility elements.
   * @return the SOAPHeader from a List of extensibility elements.
   */
  private SOAPHeader getSoapHeader(List extensibles)
  {
    SOAPHeader soapHeader = null;

    // find the soap header
    if (extensibles != null)
    {
      Iterator i = extensibles.iterator();
      while (i.hasNext() && soapHeader == null)
      {
        try
        {
          soapHeader = (SOAPHeader) i.next();
        }
        catch (ClassCastException c)
        {
        }
      }
    }
    return soapHeader;
  }

  /**
   * Get first part name from soapbind:body element.
   */
  private String getFirstPartName(BindingOperation bindingOperation)
  {
    String partName = null;
    List extList = null;
    Iterator partsIterator = null;

    // Determine if there is a list of parts by finding the soapbind:body element
    if ((extList =
      bindingOperation.getBindingInput().getExtensibilityElements())
      != null)
    {
      List partsList = null;
      Iterator extIterator = extList.iterator();
      while (extIterator.hasNext() && (partName == null))
      {
        Object extElement = extIterator.next();
        if (extElement instanceof SOAPBody)
        {
          if ((partsList = ((SOAPBody) extElement).getParts()) != null)
          {
            partsIterator = partsList.iterator();

            // Since this is a doc literal binding there should be only one part name
            if (partsIterator.hasNext())
              partName = (String) partsIterator.next();
          }
        }
      }
    }

    return partName;
  }

  public BindingOperation[] getDocLitOperations(
    EntryType messageType,
    QName partElementQName,
    BindingOperation[] wsdlOperations)
  {

    if (messageType.isType(EntryType.getEntryType(MessageValidator.TYPE_MESSAGE_REQUEST)))
    {
      return getInputDocLitOperations(partElementQName, wsdlOperations);
    }
    else if (messageType.isType(EntryType.getEntryType(MessageValidator.TYPE_MESSAGE_RESPONSE)))
    {
      return getOutputDocLitOperations(partElementQName, wsdlOperations);
    }
    else
    {
      return null; // should be one or the other
    }
  }

  private BindingOperation[] getInputDocLitOperations(
    QName partElementQName,
    BindingOperation[] wsdlOperations)
  {

    Vector potentialOps = new Vector();

    for (int i = 0; i < wsdlOperations.length; i++)
    {
      if (wsdlOperations[i].getOperation().getInput() != null)
      {
        Message message = wsdlOperations[i].getOperation().getInput().getMessage();
        // If SOAP Body child element is not present and wsdl:message does not have any wsdl:parts, that is the match 
        if (partElementQName == null)
        {
          if (message.getParts().isEmpty())
            potentialOps.add(wsdlOperations[i]);
          continue;
        }

        Iterator partsIt = message.getParts().values().iterator();
        while (partsIt.hasNext())
        {
          Part nextPart = (Part) partsIt.next();
          if (partElementQName.equals(nextPart.getElementName()))
          {
            // matching part found (doc-lit) - add to list of possible operation matches
            potentialOps.add(wsdlOperations[i]);
            break;
          }
        }
      }
    }
    return (BindingOperation[]) potentialOps.toArray(new BindingOperation[0]);
  }

  private BindingOperation[] getOutputDocLitOperations(
    QName partElementQName,
    BindingOperation[] wsdlOperations)
  {

    Vector potentialOps = new Vector();

    for (int i = 0; i < wsdlOperations.length; i++)
    {
      if (wsdlOperations[i].getOperation().getOutput() != null)
      {
        Message message = wsdlOperations[i].getOperation().getOutput().getMessage();
        // If SOAP Body child element is not present and wsdl:message does not have any wsdl:parts, that is the match
        if (partElementQName == null)
        {
          if (message.getParts().isEmpty())
            potentialOps.add(wsdlOperations[i]);
          continue;
        }

        Iterator partsIt = message.getParts().values().iterator();
        while (partsIt.hasNext())
        {
          Part nextPart = (Part) partsIt.next();
          if (partElementQName.equals(nextPart.getElementName()))
          {
            // matching part found (doc-lit) - add to list of possible operation matches
            potentialOps.add(wsdlOperations[i]);
            break;
          }
        }
      }
    }
    return (BindingOperation[]) potentialOps.toArray(new BindingOperation[0]);
  }

  /**
   * Compare soap message element part names with Parts from specified wsdl Operation
   */
  //private boolean sameParts(HashSet messageParts, Map wsdlParts)
  //{
  //
  //  // look for the soap-message operation signature
  //  Iterator i = wsdlParts.values().iterator();
  //  // build a set of Part names
  //  HashSet h = new HashSet();
  //  while (i.hasNext())
  //  {
  //    Part p = (Part) i.next();
  //    h.add(p.getName());
  //  }
  //
  //  // compare with the parts list from the message	(unordered)
  //  return (h.equals(messageParts));
  //}

  /**
   * Compare soap message element part names with Parts from specified wsdl Operation
   */
  private boolean sameParts(
    Map messageParts,
    Message wsdlMessage,
    SOAPHeader soapHeader)
  {

    String soapHeaderPart = null;
    if (soapHeader != null)
      soapHeaderPart = soapHeader.getPart();

    // check null conditions
    if (messageParts == null && wsdlMessage == null)
    {
      return true; // simple equality test
    }
    else if (messageParts == null || wsdlMessage == null)
    {
      return false;
    }

    Vector v = new Vector();
    //List wsdlParts = wsdlMessage.getOrderedParts(null);
    Map wsdlParts = null;
    if (wsdlMessage.getParts() != null)
    {
      wsdlParts = wsdlMessage.getParts();
      // look for the soap-message operation signature
      Iterator i = wsdlParts.values().iterator();
      // build a set of Part names    
      while (i.hasNext())
      {
        Part p = (Part) i.next();
        // do not include the part for the soap:header (if any)
        if (!p.getName().equals(soapHeaderPart))
        {
          // check that the part is associated with the soap:body
          v.add(new QName(p.getName()));
        }
      }
      // if one of the parts is associated with a soap:header in the binding
      // (by <soap:header part="{partname}">), remove this from the set

    }

    // compare with the parts list from the message	(ordered)
    if (v.isEmpty() && messageParts.isEmpty())
    {
      return true;
    }

    // PB: Changed to containsAll() since equals() fails when using JRE 1.4
    if (v.containsAll(messageParts.keySet())
      && (v.size() == messageParts.size()))
    {
      // Check for xsi:type mismatch
      Iterator parts = messageParts.keySet().iterator();
      QName partName, xsiType;
      while (parts.hasNext())
      {
        partName = (QName) parts.next();

        // Get xsi:type QName
        if ((xsiType = (QName) messageParts.get(partName)) != null
          && wsdlParts != null)
        {
          // Get the WSDL part definition
          Part part = (Part) wsdlParts.get(partName.getLocalPart());

          // If xsiType is NOT derived from the type of the corresponding WSDL part
          if (!isDerivedType(xsiType, part.getTypeName()))
          {
            // return false
            return false;
          }
        }
      }

      return true;
    }
    else
      return false;
    //return (v.equals(messageParts));
  }

  /**
   * Checks whether one schema type is derived from another.
   * @param extType an assumed derived type.
   * @param type an assumed base type.
   * @return true if extType is derived from type, false otherwise
   */
  public boolean isDerivedType(QName extType, QName type)
  {
    // If either of types is null, return false
    if (extType == null || type == null)
      return false;
    // If the types are equal, return true
    if (extType.equals(type))
      return true;

    // Going through all schemas 
    Iterator i = wsdlDocument.getSchemas().values().iterator();
    while (i.hasNext())
    {
      XSModel xsModel = (XSModel) i.next();
      // Retrieving the derived type definition
      XSTypeDefinition xsType = xsModel.getTypeDefinition(
        extType.getLocalPart(), extType.getNamespaceURI());
      // If it is found and derived from the base type, return true
      if (xsType != null && xsType.derivedFrom(type.getNamespaceURI(),
        type.getLocalPart(), XSConstants.DERIVATION_NONE))
      {
        return true;
      }
    }
    // extType is not derived from type, return false
    return false;
  }

  /**
  	* Get a list of QNames of parts from the soap body of the specified message
  	*/
  public Element getSoapBodyChild(Document doc)
  {

    Element opElem = null;
    if (doc != null)
    {
      Element root = doc.getDocumentElement();
      NodeList bodies =
        root.getElementsByTagNameNS(WSIConstants.NS_URI_SOAP, "Body");
      // Get the list of soap:body child element names from the request message
      if (bodies != null && bodies.getLength() > 0)
      {
        Element body = (Element) bodies.item(0);
        NodeList children = body.getChildNodes();
        for (int i = 0; i < children.getLength() && opElem == null; ++i)
        {
          Node n = children.item(i);
          if (n instanceof Element)
          {
            opElem = (Element) n;
          }
        }
      }
    }
    return opElem;
  }

  /** Check whether this message is a soap fault
   */
  public boolean isFault(Document doc)
  {
    boolean isFault = false;

    if (doc != null)
    {
      Element root = doc.getDocumentElement();
      isFault =
        (root
          .getElementsByTagNameNS(WSIConstants.NS_URI_SOAP, "Fault")
          .getLength()
          > 0);
    }

    return isFault;
  }

  /** 
   * Check whether this message has a soap body with a child element.
   */
  public boolean containsSoapBodyWithChild(Document doc)
  {
    boolean contains = false;

    if (doc != null)
    {
      contains = ((getSoapBodyChild(doc) == null) ? false : true);
    }

    return contains;
  }

  /**
   * Get SOAPAction value from the HTTP headers.
   * @param headers HTTP headers
   * @return SOAPAction value
   */
  public String getSoapAction(String headers) throws WSIException
  {
    // get SOAPAction
    String action = null;
    if (headers != null)
      action = (String) HTTPUtils.getHttpHeaderTokens(headers, ":").get("SOAPAction".toUpperCase());
    return action;
  }

  /**
   * Get a list of QNames of parts from the soap body of the specified message.
   * This method assumes RPC style message content
   */
  private QName getOperationFromMessage(Document doc)
  {
    QName operation = null;
    if (doc != null)
    {
      Element root = doc.getDocumentElement();
      NodeList bodies =
        root.getElementsByTagNameNS(WSIConstants.NS_URI_SOAP, "Body");
      if (bodies != null && bodies.getLength() > 0)
      {
        Element body = (Element) bodies.item(0);
        NodeList children = body.getChildNodes();
        for (int i = 0; i < children.getLength(); ++i)
        {
          Node n = children.item(i);
          // If element, then this is the operation name
          if (n instanceof Element)
          {
            operation = new QName(n.getNamespaceURI(), n.getLocalName());
          }
        }
      }
    }

    return operation;
  }

  /**
   * Get a list of QNames of parts from the soap body of the specified message.
   * This method assumes RPC style message content
   */
  private Map getPartListFromMessage(Document doc)
  {
    Map parts = new HashMap();
    if (doc != null)
    {
      Element root = doc.getDocumentElement();
      NodeList bodies =
        root.getElementsByTagNameNS(WSIConstants.NS_URI_SOAP, "Body");
      // Get the list of soap:body grand-child element names from the request message
      // (immediate child is the message name)
      if (bodies != null && bodies.getLength() > 0)
      {
        Element body = (Element) bodies.item(0);
        NodeList children = body.getChildNodes();
        for (int i = 0; i < children.getLength(); ++i)
        {
          Node n = children.item(i);
          if (n instanceof Element)
          {
            // this is the operation name. Its children are the parts
            NodeList grandChildren = n.getChildNodes();
            for (int j = 0; j < grandChildren.getLength(); j++)
            {
              Node m = grandChildren.item(j);
              if (m instanceof Element)
              {
                // Determine if the part has an xsi:type
                Attr attr =
                  XMLUtils.getAttribute(
                    (Element) m,
                    new QName(WSIConstants.NS_URI_XSI, "type"));

                QName xsiType = null;

                // If there is an xsi:type attribute, then get the value as a QName 
                try
                {
                  if (attr != null)
                    xsiType =
                      DOMUtils.getQName(attr.getNodeValue(), (Element) m, wsdlDocument.getDefinitions());
                }
                catch (javax.wsdl.WSDLException we)
                {
                }

                // add to the child element list
                parts.put(
                  new QName(m.getNamespaceURI(), m.getLocalName()),
                  xsiType);
              }
            }
          }
        }
      }
    }
    return parts;
  }

  public BindingOperation[] getMatchingBindingOps(
    String bindingStyle,
    Binding[] bindings)
    throws WSIException
  {

    HashSet bindingOperationsSet = new HashSet();

    // whizz through the bindings, checking for a bindingOperation matching the message
    for (int i = 0; i < bindings.length; i++)
    {

      Binding tryBinding = bindings[i];
      List bindingOps = tryBinding.getBindingOperations();

      if (bindingOps != null)
      {

        // search through binding Operations
        Iterator bindingOpIt = tryBinding.getBindingOperations().iterator();
        while (bindingOpIt.hasNext())
        {

          BindingOperation bindingOp = (BindingOperation) bindingOpIt.next();
          // check depends on which binding style is declared in the wsdl
          SOAPOperation soapOp = WSDLValidatorImpl.getSoapOperation(bindingOp);
          //GT: move this method to utils

          String style;
          if ((soapOp == null) || (style = soapOp.getStyle()) == null)
          {
            // use the style of the parent bindingOp

            SOAPBinding soapBind = WSDLValidatorImpl.getSoapBinding(tryBinding);
            //GT: move this method to utils
            if ((style = soapBind.getStyle()) == null)
            {
              style = WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC;
              //default
            }
          }
          if (style.equals(bindingStyle))
          {

            bindingOperationsSet.add(bindingOp);

          }
        }
      } // current binding has no bindingOperations, ignore
    }
    return (BindingOperation[]) bindingOperationsSet.toArray(
      new BindingOperation[0]);
  }

  /**
   * Checks whether soap:body element is literal.
   * @param extElements extensibility elements of wsdl:input or wsdl:output
   * of a binding
   */
  public boolean isLiteral(List extElems)
  {
    SOAPBody soapBody = getSOAPBody(extElems);
    if (soapBody != null
      && soapBody.getUse().equals(WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT))
      return true;
    else
      return false;
  }

  /**
   * Orders wsdl:part names keeping in mind the "parts" attribute of WSDL soap:body
   * @param messageParts a list of wsdl:partS
   * @param extElems extensibility elements in the binding
   * @return the ordered list of part names
   */
  public List orderPartNames(List messageParts, List extElems)
  {
    List orderedPartNames = new ArrayList();
    List bodyParts = null;

    SOAPBody soapBody = getSOAPBody(extElems);
    if (soapBody != null)
      bodyParts = soapBody.getParts();

    Iterator i = messageParts.iterator();
    while (i.hasNext())
    {
      String partName = ((Part) i.next()).getName();
      // If the parts attribute is not specified or contains
      // the wsdl:part name, then adding part name to the ordered list
      if (bodyParts == null || bodyParts.contains(partName))
        orderedPartNames.add(partName);
    }

    return orderedPartNames;
  }

  /**
   * Retrieves the SOAPBody object from a list of extensibility elments in binding
   * @param extElems extensibility elements
   * @return the SOAPBody element
   */
  public SOAPBody getSOAPBody(List extElems)
  {
    if (extElems == null)
      return null;
    for (Iterator i = extElems.iterator(); i.hasNext();)
    {
      Object obj = i.next();
      if (obj instanceof SOAPBody)
        return (SOAPBody) obj;
    }

    return null;
  }
 
  public List resolveSameNamespaces(List schemaElements)
  {
  	List namespaces = new ArrayList();
  	List result = new ArrayList();
  	Iterator i = schemaElements.iterator();
    while (i.hasNext())
    {
      Element schema = (Element) i.next();
      String targetNamespace = schema.getAttribute(Constants.ATTR_TARGET_NAMESPACE);
      if (!namespaces.contains(targetNamespace))
      {
        namespaces.add(targetNamespace);
    	List schemas = getSchemasWithSameNamespace(schemaElements, targetNamespace);
    	if (schemas.size() == 1)
      	{
      	  result.add(schema);
      	}
    	else
    	{
    		// copying all the NS declarations from wsdl:definitions wsdl:types
      //copyNSDeclarations(root, schema);
      copyNSDeclarations((Element) schema.getParentNode(), schema);
      // Replacing all relative schemaLocation URIs with absolute ones
      //replaceRelativeURIs(schema, wsdlURI);
      // Serialize the schema elements inside the Types, then use this as
      // the schema string for the validation
      //String schemaString =
      //  DOM2Writer.nodeToString(schema);
      // schemaStrings.add(schemaString);
      	}
      }
    }
  	return null;
  }
  	
  public List getSchemasWithSameNamespace(List schemaElements, String targetNamespace)
  { 
  	List result = new ArrayList();
    Iterator i = schemaElements.iterator();
    while (i.hasNext())
    {
      Element schema = (Element)i.next();
      String schemaTargetNamespace = schema.getAttribute(Constants.ATTR_TARGET_NAMESPACE);
      if (schemaTargetNamespace == null)
       	schemaTargetNamespace = "";
        
      if (schemaTargetNamespace.equals(targetNamespace))
      {
       	result.add(schema);
      }
    }
    return result;
  }

  public boolean duplicateNamespacesDetected(List schemaElements)
  { 
  	boolean result = false;
    List namespaces = new ArrayList();
    Iterator i = schemaElements.iterator();
    while (i.hasNext())
    {
    	Element schema = (Element)i.next();
        String targetNamespace = schema.getAttribute(Constants.ATTR_TARGET_NAMESPACE);
        if (targetNamespace == null)
        	targetNamespace = "";
        
        if (namespaces.contains(targetNamespace))
        {
        	result = true;
        	break;
        }
        else
        {
        	namespaces.add(targetNamespace);
        }
    }
    return result;
  }

  /**
   * Returns true if these tests should be run (depending on the analyzer
   * config)
   */
  public boolean runTests() { return testable; }
  
  public void validateArtifact() throws WSIException {
      // Get the log file reader
      LogReader logReader = DocumentFactory.newInstance().newLogReader();

      // Create log reader callback
      LogProcessor envelopeProcessor = new LogProcessor(this);

      // Start reading the log file
      logReader.readLog(analyzerConfig.getLogLocation(), envelopeProcessor);
  }

  protected class LogProcessor implements MessageEntryHandler {
      LogValidator validator = null;

    /**
     * Create message processor as a log reader callback function.
     */
      LogProcessor(LogValidator validator) {
          this.validator = validator;
      }

    /**
     * Process artifact reference.
     */
    public void processArtifactReference(ArtifactReference artifactReference)
            throws WSIException {
        reporter.addArtifactReference(artifactReference);
    }

    /**
     * Process a single log entry.
     */
    public void processLogEntry(EntryContext entryContext) throws WSIException {
        validator.validate(entryContext);
    }
  }

  public void cleanup() throws WSIException {
	  super.cleanup();
	  wsdlDocument = null;
  }
}