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

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.Fault;
import javax.wsdl.Import;
import javax.wsdl.Message;
import javax.wsdl.Operation;
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.soap.SOAPAddress;
import javax.xml.namespace.QName;

import org.apache.xerces.util.URI;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.analyzer.config.WSDLElement;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLDocument;
import org.eclipse.wst.wsi.internal.core.wsdl.WSDLUtils;

/**
 * Provide a normalized set of data relating to the service under test.
 * For example, with endpoint correlation and wsdlElement of type "message" 
 * there could be multiple matches for most element types including WSDL Service.
 * (though the objective is to ensure filtering to a single service if at all possible). 
 * 
 * @author gturrell
 */

// ADD:could be better as a singleton?

public class CandidateInfo
{

  // Normalized fixed correlation data derived from the analyzer config and the wsdl,
  // representing what we know about the service from these two sources.  
  private Definition[] definitions = null;

  private Import[] imports = null;
  private Types[] types = null;

  private Message[] messages = null;
  private Operation[] operations = null;
  private PortType[] portTypes = null;
  private Binding[] bindings = null;
  private Port[] ports = null;

  private URI[] endPoints = null; // list obtainable from a port

  private WSDLDocument wsdlDocument; // reference probably not desirable here

  /**
   * Constructor for CandidateInfo.
   * Extract normalised entry data from wsdl, according to config wsdlElement & serviceLocation
   * @param serviceReference a ServiceReference object.
   * @param wsdlDocument a WSDL document.
   * @throws WSIException if problems occur creating CandidateInfo object.
   */
  public CandidateInfo(
    ServiceReference serviceReference,
    WSDLDocument wsdlDocument)
    throws WSIException
  {

    // ADD: check for null document?

    WSDLElement wsdlElement = serviceReference.getWSDLElement();

    this.wsdlDocument = wsdlDocument;

    /*
     * Generalised fields independent of wsdlElement:
     */
    // ADD: check whether these need to be either expanded or filtered down.
    // Assume WSDL4J pulls int the full tree at the root document for now		
    //this.imports = wsdlDocument.getImports();

    // ... or if only down to first level....
    this.imports =
      (Import[]) getAllImports(
        wsdlDocument.getDefinitions()).toArray(new Import[] {
    });

    /* Definitions. 
     * Note that the the first array element is for the root doc
     * which contains all WSDL elements in scope via <import> declarations,
     * as well as the root document itself. Therefore the second definitions 
     * array element and above are redundant, but *may* prove useful to the assertion
     * code.
     */

    this.definitions = new Definition[imports.length + 1];
    // allow room for root doc		

    this.definitions[0] = wsdlDocument.getDefinitions(); // root document    

    // Allocate array for types elements
    Types[] tempTypes = new Types[definitions.length];

    int typesCount = 0;

    if (definitions[0].getTypes() != null)
    {
      tempTypes[0] = this.definitions[0].getTypes(); // root document	
      typesCount++;
    }

    // Definitions from other (imported) wsdls correlating to the candidate
    // Only one level down for now
    for (int i = 0; i < imports.length; i++)
    {
      if (((definitions[i + 1] = imports[i].getDefinition()) != null)
        && (definitions[i + 1].getTypes() != null))
      {
        tempTypes[typesCount] = definitions[i + 1].getTypes();
        typesCount++;
      }
    }

    if (typesCount > 0)
    {
      this.types = new Types[typesCount];

      for (int i = 0; i < typesCount; i++)
        this.types[i] = tempTypes[i];
    }
    /* 
     * Populate element hierachy:
     * Port
     * Binding
     * PortType
     * operation(s)
     * message(s)
     */

    if (wsdlElement.isPort())
    {

      Port port = null;

      // Use parentElementName to qualify the port within a service.		
      QName serviceName = wsdlElement.getParentElementQName();
      Service[] s = wsdlDocument.getServices();
      String portName = wsdlElement.getName();
      for (int i = 0; i < s.length && port == null; i++)
      {
        if (s[i].getQName().equals(serviceName))
        {
          port = s[i].getPort(portName);
        }
      }

      if (port == null)
      {
        throw new WSIException(
          "WSDL Port \'"
            + portName
            + "\' for Service \'"
            + serviceName
            + "\' not found in service description");
      }
      else
      {
        this.ports = new Port[] { port };
        // ADD: do serviceLocation check for soapbind:address?
        descendents(port);
      }

      // ADD: the following could be instantiated here instead to refine context info
      // definitions 
      // imports 
      // types

    }

    else if (wsdlElement.isBinding())
    {
      if (wsdlElement.getQName() != null
        && wsdlElement.getQName().getLocalPart() != null
        && wsdlElement.getQName().getLocalPart().length() > 0)
      {
        Binding binding =
          wsdlDocument.getDefinitions().getBinding(wsdlElement.getQName());

        if (binding == null)
        {
          throw new WSIException(
            "WSDL Binding named \'"
              + wsdlElement.getQName()
              + "\' not found in service description");
        }
        else
        {
          this.bindings = new Binding[] { binding };

          // the rest ... below binding:	
          // portTypes from binding
          // operations from portTypes
          // messages from operations
          descendents(binding);

          // above binding:
          // ports
          // definitions, imports, types (future?)				
          // ancestors(bindings);
        }
      }
    }

    else if (wsdlElement.isPortType())
    {

      PortType portType =
        wsdlDocument.getDefinitions().getPortType(wsdlElement.getQName());
      this.portTypes = new PortType[] { portType };

      if (portType == null)
      {
        throw new WSIException(
          "WSDL PortType named \'"
            + wsdlElement.getQName()
            + "\' not found in service description");
      }
      else
      {
        this.portTypes = new PortType[] { portType };
        // the rest ... below portType:	
        descendents(portType);

        // above portType:
        // ports
        // definitions, imports, types (future) ?
        //ancestors(portTypes);		
      }
    }
    else if (wsdlElement.isOperation())
    {

      Operation operation = null;
      String configOpName = wsdlElement.getName();

      // Use parentElementName to qualify the operation within a portType.
      QName portTypeName = wsdlElement.getParentElementQName();
      PortType[] p = wsdlDocument.getPortTypes();
      for (int i = 0; i < p.length && operation == null; i++)
      {
        if (p[i].getQName().equals(portTypeName))
        {
          // wsdl4j available method call below implies that only 
          // name+inputname+outputname uniquely defines operation! 
          // Since we do not have <input> & <output> name information
          // available in the config, use this instead for now: - 
          // Get the first operation we find:
          Iterator opIt = p[i].getOperations().iterator();
          Operation op = null;
          while (opIt.hasNext() && operation == null)
          {
            op = (Operation) opIt.next();
            if (configOpName.equals(op.getName()))
            {
              operation = op;
            }
          }
        }
      }

      if (operation == null)
      {
        throw new WSIException(
          "No WSDL Operation named \'"
            + wsdlElement.getQName()
            + "\' found in service description");
      }
      else
      {
        this.operations = new Operation[] { operation };

        descendents(operation);
        //ancestors(operations);
      }
    }

    else if (wsdlElement.isMessage())
    {

      Message message =
        wsdlDocument.getDefinitions().getMessage(wsdlElement.getQName());
      if (message == null)
      {
        throw new WSIException(
          "No WSDL Message named \'"
            + wsdlElement.getQName()
            + "\' found in service description");
      }
      else
      {
        this.messages = new Message[] { message };

        //ancestors(messages); 
      }
    }

    else
    {
      throw new WSIException(
        "Unrecognised <WSDLElement type> in config: " + wsdlElement.getType());
    }

    // get info about the effective service location (s)
    //this.endPoints = deriveEndpoints(analyzerConfig, this.ports, this.definitions);
    this.endPoints =
      deriveEndpoints(serviceReference, this.ports, this.definitions);
  }

  /** 
     * ancestor code is not used at present.
     * 
     */
  /*   
     protected void ancestors(Port[] ports) {
     	// no ancestors of Port required (for now)
     } 	    
     protected void ancestors(Binding[] bindings) {	    
    		// Ports from Bindings  1-2-1
     	
     	// *** cheat for now - get ports from all services in the wsdl doc
     	// ADD: find correct mapping based on the supplied bindings
     	Service[] service = wsdlDocument.getServices();
     	HashSet set = new HashSet();
  		for (int i=0; i>service.length; i++) {
  			set.add(service[i].getPorts());  
  		}
  			
  		// assign the parent group and process the grandparents if any								
  		ancestors(this.ports = (Port[])set.toArray(this.ports = new Port[0]));
     }
     protected void ancestors(PortType[] portTypes) {	    
    		// Bindings from PortTypes  1-2-1
     	
     	// add have to start with all bindings in doc and search for those
     	// with the portType  
     	HashSet set = new HashSet();
  		for (int i=0; i>portTypes.length; i++) {
  		// set.add(portTypes[i].get());  
  		}
  			
  		// assign the parent group and process the grandparents if any								
  		ancestors(this.bindings = (Binding[])set.toArray(this.bindings = new Binding[0]));
     }
     protected void ancestors(Operation[] operations) {	    
    		// PortTypes from Operations  1-2-1
     	  
     	HashSet set = new HashSet();
  		for (int i=0; i>operations.length; i++) {
  			// set.add(operations[i].get());  
  		}
  			
  		// assign the parent group and process the grandparents if any								
  		ancestors(this.portTypes = (PortType[])set.toArray(this.portTypes = new PortType[0]));
     }
     protected void ancestors(Message[] messages) {	    
    		// Operations from Messages  1-2-1
     	// ADD fix it!  
     	HashSet set = new HashSet();
  		for (int i=0; i>messages.length; i++) {
  			// set.add(messages[i].get());  
  		}
  			
  		// assign the parent group 	
  		this.portTypes = (PortType[])set.toArray(this.portTypes = new PortType[0]);
     }
  */

  /**
   * Descendant method for completing candidate service context creation.
   * @param port  a Port object
   * @throws WSIException if port is null.
   */
  protected void descendents(Port port) throws WSIException
  {
    // Binding from Port  1-2-1

    if (port == null)
    {
      throw new WSIException("Internal error: expected a Port value");
    }
    else
    {
      this.bindings = new Binding[] { port.getBinding()};
      if (this.bindings[0] != null)
      {
        /* Assign the child group and process the grandchildren if any.
        * Null argument value passed into the following method would 
        * suggest a WSDL definition inconsistency
        * which will be picked up during Description Artifact TA testing.
        */
        descendents(this.bindings[0]);
      }
    }
  }

  /**
   * Descendant method for completing candidate service context creation.
   * @param binding  a Binding object
   * @throws WSIException if binding is null.
   */
  protected void descendents(Binding binding) throws WSIException
  {
    // portType from Binding 1-2-1

    if (binding == null)
    {
      throw new WSIException("Internal error: expected a Binding value");
    }
    else
    {
      this.portTypes = new PortType[] { binding.getPortType()};
      if (this.portTypes[0] != null)
      {
        /* Assign the child group and process the grandchildren if any.
        	* Null argument value passed into the following method would 
        	* suggest a WSDL definition inconsistency
        	* which will be picked up during Description Artifact TA testing.
        	*/
        descendents(this.portTypes[0]);

        // Get any messages that are referenced from headers and headerfaults

        BindingOperation bindingOperation;

        // Get reference to definition
        Definition definition = definitions[0];

        // If there are messages already, then get them as a collection
        HashSet messageSet = new HashSet();
        if (messages != null)
        {
          for (int i = 0; i < messages.length; i++)
          {
            messageSet.add(messages[i]);
          }
        }

        // Get the messages that are referenced only by a binding 
        HashSet bindingMessages = WSDLUtils.findMessages(definition, binding);

        // Add these messages to the complete message list  
        messageSet.addAll(bindingMessages);

        // Create array from message set
        this.messages =
          (Message[]) messageSet.toArray(this.messages = new Message[0]);
      }
    }
  }

  /**
   * Descendant method for completing candidate service context creation.
   * @param portType  a PortType object
   * @throws WSIException if portType is null.
   */
  protected void descendents(PortType portType) throws WSIException
  {
    // Operations from PortType 1-2-n

    if (portType == null)
    {
      throw new WSIException("Internal error: expected a PortType value");
    }
    else
    {
      this.operations =
        (Operation[]) (portType
          .getOperations()
          .toArray(this.operations = new Operation[0]));
      if (this.operations.length > 0)
      {
        descendents(this.operations);
      }
    }
  }

  /**
     * Descendant method for completing candidate service context creation.
     * @param operation  a Operation object
     * @throws WSIException if operation is null.
     */
  protected void descendents(Operation operation) throws WSIException
  {
    // Messages from Operation

    if (operation == null)
    {
      throw new WSIException("Internal error: expected an Operation value");
    }
    else
    {
      descendents(new Operation[] { operation });
    }
  }

  /**
   * Descendant method for completing candidate service context creation.
   * @param operations  an array of operations.
   * @throws WSIException if operations is null.
   */
  protected void descendents(Operation[] operations) throws WSIException
  {
    // Messages from Operations 1-2-n

    if (operations == null)
    {
      throw new WSIException("Internal error: expected an Operation[] value");
    }

    HashSet set = new HashSet();
    for (int i = 0; i < operations.length; i++)
    {
      if (operations[i].getInput() != null)
        set.add(operations[i].getInput().getMessage()); //1-2-1
      if (operations[i].getOutput() != null)
        set.add(operations[i].getOutput().getMessage()); //1-2-1

      // get messages associated with faults for this operation 
      // 1-2-n
      Iterator it = operations[i].getFaults().values().iterator();
      while (it.hasNext())
      {
        set.add(((Fault) it.next()).getMessage());
      }
    }
    this.messages = (Message[]) set.toArray(this.messages = new Message[0]);
    // no descendents of messages so stop.
  }

  /**
   * Provide a recursive non-repeating list of imports for the specified
   * WSDL document definition.
   */
  /*   private HashSet getAllImports(Definition rootDef) throws WSIException {
     	
     	HashSet importSet = new HashSet();
     	
     	Collection importList =  rootDef.getImports().values();
     	Iterator i = importList.iterator();
     	
     	while (i.hasNext()) {
     		Import nextImport = (Import)(i.next());
     		if (nextImport != null) {
     			// its a wsdl document
     			importSet.addAll(getAllImports(nextImport.getDefinition()));
     		}   			
     	}
     	
     	return (importSet);
     }
   */
  private HashSet getAllImports(Definition rootDef) throws WSIException
  {

    HashSet importSet = new HashSet();

    Map importMap = rootDef.getImports();
    Iterator i = importMap.values().iterator();

    while (i.hasNext())
    {
      List nextImportList = (List) (i.next());
      Iterator listIt = nextImportList.iterator();
      while (listIt.hasNext())
      {
        Import nextImport = (Import) listIt.next();
        if (nextImport != null)
        {
          // its a wsdl document
          importSet.add(nextImport);
          if (nextImport.getDefinition() != null)
          {
            HashSet subTreeImports = getAllImports(nextImport.getDefinition());
            Iterator subIt = subTreeImports.iterator();
            while (subIt.hasNext())
            {
              importSet.add((Import) (subIt.next()));
            }
          }
        }
      }
    }

    return (importSet);
  }

  /**
   * get all service location endpoint values
   * relevant to the service under test.
   * 
   * If the service location is specified in the config we use
   * just that.
   * Otherwise, if the port is specified, we get all endpoints
   * associated with that port.
   * If we have neither the service location value or the port,
   * then all endpoints in the definition are used.
   */
  private URI[] deriveEndpoints(
  //AnalyzerConfig analyzerConfig, 
  ServiceReference serviceReference, Port[] ports, Definition[] definitions)
  {

    URI[] endp = null;
    //Port port = null;	
    try
    {
      String serviceLocation = null;
      // try service location...
      //if ((serviceLocation = analyzerConfig.getServiceLocation()) != null) {      
      if ((serviceLocation = serviceReference.getServiceLocation()) != null)
      {
        endp = new URI[] { new URI(serviceLocation)};
      }
      //else if (analyzerConfig.getWSDLElement().isPort()) {
      else if (serviceReference.getWSDLElement().isPort())
      {
        if (ports.length != 1)
        {
          throw new WSIException("Internal error - expected 1-element Port array");
        }
        //else {
        //	port = ports[0]; // if Port was given in config, there is just one
        //}
        //QName soapAddress = new QName(WSIConstants.NS_URI_WSDL_SOAP, "address");
        Iterator i = ports[0].getExtensibilityElements().iterator();
        while (i.hasNext() && serviceLocation == null)
        {
          ExtensibilityElement extElem = (ExtensibilityElement) i.next();
          if (extElem instanceof SOAPAddress)
          {
            //if (extEl.getElementType().equals(soapAddress) {
            // this element is our SOAPAddress - get the location
            serviceLocation = ((SOAPAddress) extElem).getLocationURI();
            endp = new URI[] { new URI(serviceLocation)};
          }
        }
      }
      else
      { // no port info from config, so supply all in document
        // QName soapAddress = new QName(WSIConstants.NS_URI_WSDL_SOAP, "address");
        HashSet endpointSet = new HashSet();
        Iterator i = definitions[0].getExtensibilityElements().iterator();
        while (i.hasNext())
        {
          ExtensibilityElement extElem = (ExtensibilityElement) i.next();
          if (extElem instanceof SOAPAddress)
          {
            //if (extEl.getElementType().equals(soapAddress) {
            // this element is our SOAPAddress - get the location
            endpointSet.add(((SOAPAddress) extElem).getLocationURI());
          }
        }
        // Convert the derived List to a URI array
        endp = (URI[]) endpointSet.toArray(endp = new URI[0]);
      }
    }
    catch (Exception e)
    {
    }
    return endp;
  }

  /**
   * Returns the binding.
   * @return Binding
   */
  public Binding[] getBindings()
  {
    return bindings;
  }

  /**
   * Returns the endPoints.
   * @return URI[]
   */
  public URI[] getEndPoints()
  {
    // get list of matching endpoint(s) associated with service.
    return endPoints;
  }

  /**
  * Returns the endPoints matching the specified host and port.
  * @param hostAndPort  host and port location.
  * @return URI[] if matched, null otherwise.
  */
  public URI[] getEndPoints(String hostAndPort)
  {
    // get list of matching endpoints associated with service,
    // having the specified host and port configuration
    String port;

    Vector matchedEndpoints = new Vector();
    for (int i = 0; i < endPoints.length; i++)
    {
      // PB: If the endpoint does not contain a port number, then default it to "80"
      port =
        (endPoints[i].getPort() == -1)
          ? "80"
          : String.valueOf(endPoints[i].getPort());
      if (hostAndPort.equals(endPoints[i].getHost() + ":" + port))
      {
        matchedEndpoints.add(endPoints[i]);
      }
    }
    return (URI[]) matchedEndpoints.toArray(new URI[0]);
  }

  /**
   * Returns the operation.
   * @return Operation
   */
  public Operation[] getOperations()
  {
    return operations;
  }

  /**
   * Returns the portType.
   * @return PortType
   */
  public PortType[] getPortType()
  {
    return portTypes;
  }

  /**
   * Returns true if the hostAndPort matches at least one context endpoint.
   * @param hostAndPortString a host and port location.
   * @return true if the hostAndPort matches at least one context endpoint.
   * @throws WSIException if given hostandPort String does not convert to URI.
   */
  public boolean hasHostAndPort(String hostAndPortString) throws WSIException
  {
    URI hostAndPort;
    try
    {
      hostAndPort = new URI(hostAndPortString);
    }
    catch (Exception e)
    {
      throw new WSIException(
        "Could not convert string to URI: " + hostAndPortString);
    }
    String host = hostAndPort.getHost();
    int port = hostAndPort.getPort();
    for (int i = 0; i < this.endPoints.length; i++)
    {
      if (this.endPoints[i].getHost().equals(host)
        && this.endPoints[i].getPort() == port)
      {
        return true;
      }
    }
    return false; // for now
  }

  /**
   * Returns the definitions.
   * @return Definition[]
   */
  public Definition[] getDefinitions()
  {
    return definitions;
  }

  /**
   * Returns the imports.
   * @return Import[]
   */
  public Import[] getImports()
  {
    return imports;
  }

  /**
   * Returns the messages.
   * @return Message[]
   */
  public Message[] getMessages()
  {
    return messages;
  }

  /**
   * Returns the ports.
   * @return Port[]
   */
  public Port[] getPorts()
  {
    return ports;
  }

  /**
   * Returns the portTypes.
   * @return PortType[]
   */
  public PortType[] getPortTypes()
  {
    return portTypes;
  }

  /**
   * Returns the types.
   * @return Types[]
   */
  public Types[] getTypes()
  {
    return types;
  }
  /**
   * Returns the wsdlDocument.
   * @return WSDLDocument
   */
  public WSDLDocument getWsdlDocument()
  {
    return wsdlDocument;
  }

  /**
   * Return the definition element that contains the types element.
   * @param types a Types object.
   * @return the definition element that contains the types element.
   */
  public Definition getDefinition(Types types)
  {
    Definition definition = null;
    Types checkTypes;

    for (int i = 0; i < definitions.length && definition == null; i++)
    {
      if (((checkTypes = definitions[i].getTypes()) != null)
        && (checkTypes.equals(types)))
      {
        definition = definitions[i];
      }
    }

    return definition;
  }

  /**
   * Return the definition element that contains the binding element.
   * @param binding a Binding object.
   * @return the definition element that contains the binding element.
   */
  public Definition getDefinition(Binding binding)
  {
    Definition definition = null;

    for (int i = 0; i < definitions.length && definition == null; i++)
    {
      if (definitions[i].getBinding(binding.getQName()) != null)
        definition = definitions[i];
    }

    return definition;
  }

  /**
   * Return the definition element that contains the portType element.
   * @param portType a PortType object.
   * @return the definition element that contains the portType element.
   */
  public Definition getDefinition(PortType portType)
  {
    Definition definition = null;

    for (int i = 0; i < definitions.length && definition == null; i++)
    {
      if (definitions[i].getPortType(portType.getQName()) != null)
        definition = definitions[i];
    }

    return definition;
  }

  /**
   * Return the definition element that contains the message.
   * @param message a Message object.
   * @return the definition element that contains the message.
   */
  public Definition getDefinition(Message message)
  {
    Definition definition = null;

    for (int i = 0; i < definitions.length && definition == null; i++)
    {
      if (definitions[i].getMessage(message.getQName()) != null)
        definition = definitions[i];
    }

    return definition;
  }

}
