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

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import javax.wsdl.Binding;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.PortType;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
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;

/**
 * Set of XML related utilities.
 * 
 * @author Peter  Brittenham (peterbr@us.ibm.com)
 * @version 1.0.1
 */
public final class WSDLUtils
{

  /**
   * Method isRpcLiteral.
   * @param bindingStyle a binding style.
   * @param operation a WSDL binding operation artifact.
   * @return true if binding is rpc literal.
   */
  public static boolean isRpcLiteral(
    String bindingStyle,
    BindingOperation operation)
  {
    return checkStyleAndUse(
      WSIConstants.ATTRVAL_SOAP_BIND_STYLE_RPC,
      WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT,
      bindingStyle,
      operation);
  }

  /**
   * Method isDocLiteral.
   * @param bindingStyle  the binding style.
   * @param operation a WSDL binding operation.
   * @return true if binding is document literal. 
   */
  public static boolean isDocLiteral(
    String bindingStyle,
    BindingOperation operation)
  {
    return checkStyleAndUse(
      WSIConstants.ATTRVAL_SOAP_BIND_STYLE_DOC,
      WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT,
      bindingStyle,
      operation);
  }

  /**
   * Method checkStyleAndUse.
   */
  private static boolean checkStyleAndUse(
    String checkStyle,
    String checkUse,
    String bindingStyle,
    BindingOperation bindingOperation)
  {
    boolean styleFound = false;
    boolean styleAndUseFound = false;

    // Find the soapbind:operation element
    SOAPOperation soapOperation = getSoapOperation(bindingOperation);

    // If there are no ext elements, then check against binding style
    if ((soapOperation == null) || (soapOperation.getStyle() == null))
    {
      if (checkStyle.equals(bindingStyle))
        styleFound = true;
    }

    else
    {
      if (checkStyle.equals(soapOperation.getStyle()))
        styleFound = true;
    }

    // If style found then check use
    if (styleFound)
    {
      // Find the soapbind:body element
      SOAPBody soapBody = getInputSoapBody(bindingOperation);

      // If there are no soapbind:body, then check against default use value
      if ((soapBody == null) || (soapBody.getUse() == null))
      {
        if (checkUse.equals(WSIConstants.ATTRVAL_SOAP_BODY_USE_LIT))
          styleAndUseFound = true;
      }

      else
      {
        if (checkUse.equals(soapBody.getUse()))
          styleAndUseFound = true;
      }
    }

    return styleAndUseFound;
  }

  /**
   * Get soapbind:binding.
   * @param binding  a Binding object.
   * @return soapbind:binding.
   */
  public static SOAPBinding getSoapBinding(Binding binding)
  {
    SOAPBinding soapBinding = null;

    List extElements = null;

    // Find the soapbind:operation element
    if ((extElements = binding.getExtensibilityElements()) != null)
    {
      for (Iterator iterator = extElements.iterator();
        iterator.hasNext() && (soapBinding == null);
        )
      {
        Object obj = iterator.next();

        if (obj instanceof SOAPBinding)
        {
          soapBinding = (SOAPBinding) obj;
        }
      }
    }

    return soapBinding;
  }

  /**
   * Get soapbind:operation.
   * @param bindingOperation  a BindingOperation object.
   * @return soapbind:operation.
   */
  public static SOAPOperation getSoapOperation(BindingOperation bindingOperation)
  {
    SOAPOperation soapOperation = null;

    List extElements = null;

    // Find the soapbind:operation element
    if ((extElements = bindingOperation.getExtensibilityElements()) != null)
    {
      for (Iterator iterator = extElements.iterator();
        iterator.hasNext() && (soapOperation == null);
        )
      {
        Object obj = iterator.next();

        if (obj instanceof SOAPOperation)
        {
          soapOperation = (SOAPOperation) obj;
        }
      }
    }

    return soapOperation;
  }

  /**
   * Get soapbind:body from input element.
   * @param bindingOperation  the BindingOperation object.
   * @return soapbind:body from input element.
   */
  public static SOAPBody getInputSoapBody(BindingOperation bindingOperation)
  {
    SOAPBody soapBody = null;

    List extElements = null;

    // Find the soapbind:body element
    if ((extElements =
      bindingOperation.getBindingInput().getExtensibilityElements())
      != null)
    {
      for (Iterator iterator = extElements.iterator();
        iterator.hasNext() && (soapBody == null);
        )
      {
        Object obj = iterator.next();

        if (obj instanceof SOAPBody)
        {
          soapBody = (SOAPBody) obj;
        }
      }
    }

    return soapBody;
  }

  /**
   * Find messages referenced by a header or headerfault.
   * @param definition  a Definition object.
   * @param binding  a Binding object.
   * @return messages referenced by a header or headerfault.
   */
  public static HashSet findMessages(Definition definition, Binding binding)
  {
    BindingOperation bindingOperation;

    HashSet tempMessages, bindingMessages = new HashSet();

    HashSet portTypeMessages = findMessages(binding.getPortType());

    // Process each operation
    Iterator iterator = binding.getBindingOperations().iterator();
    while (iterator.hasNext())
    {
      bindingOperation = (BindingOperation) iterator.next();

      // Process the input and then the output
      if (bindingOperation.getBindingInput() != null)
      {
        tempMessages =
          findMessages(
            bindingOperation
              .getBindingInput()
              .getExtensibilityElements()
              .iterator(),
            portTypeMessages,
            definition);

        // Add messages to binding message set
        bindingMessages.addAll(tempMessages);
      }

      // Process output
      if (bindingOperation.getBindingOutput() != null)
      {
        tempMessages =
          findMessages(
            bindingOperation
              .getBindingOutput()
              .getExtensibilityElements()
              .iterator(),
            portTypeMessages,
            definition);

        // Add messages to binding message set
        bindingMessages.addAll(tempMessages);
      }
    }

    return bindingMessages;
  }

  /**
   * Find the messages that are referenced by a header or headerfault.
   * @param portType a PortType object.
   * @return he messages that are referenced by a header or headerfault.
   */
  public static HashSet findMessages(PortType portType)
  {
    HashSet messageSet = new HashSet();
    ExtensibilityElement extElement;
    Operation operation;

    Iterator iterator = portType.getOperations().iterator();
    while (iterator.hasNext())
    {
      // Get next operation to process
      operation = (Operation) iterator.next();

      // Get input and output message
      if (operation.getInput() != null)
        messageSet.add(operation.getInput().getMessage());
      if (operation.getOutput() != null)
        messageSet.add(operation.getOutput().getMessage());

      // Process any faults
      Iterator faults = operation.getFaults().values().iterator();
      while (faults.hasNext())
      {
        messageSet.add(((Fault) faults.next()).getMessage());
      }
    }

    return messageSet;
  }

  /**
   * Find the messages that are referenced by a header or headerfault.
   * @param extElementList a list of external elements.
   * @param messageSet a set of messages.
   * @param definition a Definition object.
   * @return the messages that are referenced by a header or headerfault.
   */
  protected static HashSet findMessages(
    Iterator extElementList,
    HashSet messageSet,
    Definition definition)
  {
    HashSet returnSet = new HashSet();
    ExtensibilityElement extElement;
    Message saveMessage = null;

    while (extElementList.hasNext())
    {
      // Get ext. element
      extElement = (ExtensibilityElement) extElementList.next();

      QName messageQName;
      Message message;

      // If this is a soap:header element, then check for message reference
      if (extElement instanceof SOAPHeader)
      {
        SOAPHeader soapHeader = (SOAPHeader) extElement;
        if ((messageQName = soapHeader.getMessage()) != null)
        {
          // If message not found, then create a dummy message element
          if ((message = definition.getMessage(messageQName)) == null)
          {
            message = definition.createMessage();
            message.setQName(messageQName);
            message.setUndefined(true);
          }

          if (!messageSet.contains(message))
          {
            returnSet.add(message);
            saveMessage = message;
          }
        }

        // Process any header faults within this header
        Iterator headerFaultList = soapHeader.getSOAPHeaderFaults().iterator();
        while (headerFaultList.hasNext())
        {
          // Get soap header fault
          SOAPHeaderFault soapHeaderFault =
            (SOAPHeaderFault) headerFaultList.next();
          if ((messageQName = soapHeaderFault.getMessage()) != null)
          {
            // If message not found, then create a dummy message element
            if ((message = definition.getMessage(messageQName)) == null)
            {
              message = definition.createMessage();
              message.setQName(messageQName);
              message.setUndefined(true);
            }

            // If message not in message set and return set, then add it  
            if (!messageSet.contains(message)
              && ((saveMessage == null)
                || (saveMessage != null
                  && !saveMessage.getQName().equals(message.getQName()))))
              returnSet.add(message);
          }
        }
      }
    }

    return returnSet;
  }
}
