/*******************************************************************************
 * 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 org.apache.xerces.dom.ElementImpl;
import org.eclipse.wst.wsi.internal.core.xml.dom.ElementLocation;

import com.ibm.wsdl.*;
import com.ibm.wsdl.util.StringUtils;
import com.ibm.wsdl.util.xml.*;

import org.w3c.dom.*;
import org.xml.sax.*;

import javax.wsdl.*;
import javax.wsdl.extensions.*;
import javax.wsdl.factory.*;
import javax.xml.namespace.*;
import javax.xml.parsers.*;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * This class is a specialization of com.ibm.wsdl.xml.WSDLReaderImpl in WSDL4J.
 * 
 * @version 1.0.1
 * @author Peter Brittenham  (peterbr@us.ibm.com)
 */
public class WSDLReaderImpl extends com.ibm.wsdl.xml.WSDLReaderImpl
{
  // WSDL element list.
  protected WSDLElementList wsdlElementList = new WSDLElementList();

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseDefinitions(java.lang.String, org.w3c.dom.Element, java.util.Map)
   */
  protected Definition parseDefinitions(
    String documentBaseURI,
    Element defEl,
    Map importedDefs)
    throws WSDLException
  {
    Definition def =
      super.parseDefinitions(documentBaseURI, defEl, importedDefs);

    // Try to add element to list
    addElementToList(defEl, def);

    return def;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseImport(org.w3c.dom.Element, javax.wsdl.Definition, java.util.Map)
   */
  protected Import parseImport(Element element, Definition definition, Map map)
    throws WSDLException
  {
    /*boolean wasEx = false;
    if (def.getDocumentBaseURI()!=null){
    	File f = new File(def.getDocumentBaseURI());
    	if (f.getParent()!=null && importEl.getAttribute("location")!=null){		
    	   f = new File(f.getParent()+"/"+importEl.getAttribute("location"));
    	   
    	}
    } else wasEx = false;
      
    Import importDef = super.parseImport(importEl, def, importedDefs);
    
    // Try to add element to list
    addElementToList(importEl, importDef);
    
    return importDef;*/

    /*Import import1 = definition.createImport();
    String s = DOMUtils.getAttribute(element, "namespace");
    String s1 = DOMUtils.getAttribute(element, "location");
    if (s != null)
    	import1.setNamespaceURI(s);
    if (s1 != null) {
    	if (importDocuments) {
    		String s2 = definition.getDocumentBaseURI();
    		try {
    
    			URL url1 = s2 == null ? null : StringUtils.getURL(null, s2);
    			URL url = StringUtils.getURL(url1, s1);
    			InputStream inputstream =
    				StringUtils.getContentAsInputStream(url);
    			inputstream.close();
    		} catch (IOException ex) {
    			//import1.setLocationURI(null);
    			addElementToList(element, import1);
    			return import1;
    		} catch (Throwable ex) {
    			throw new WSDLException(
    				"OTHER_ERROR",
    				"Unable to resolve imported document at '" + s1 + "'.",
    				ex);
    		}
    
    	}
    }
    Import importDef = super.parseImport(element, definition, map);
    addElementToList(element, importDef);*/
    Import import1 = definition.createImport();
    String s = DOMUtils.getAttribute(element, "namespace");
    String s1 = DOMUtils.getAttribute(element, "location");
    if (s != null)
      import1.setNamespaceURI(s);
    // ADD: check "location" attribute for empty 
    // string to prevent self-defenition assigning
    if ((s1 != null) && (s1.length() > 0))
    {
      import1.setLocationURI(s1);
      if (importDocuments)
        try
        {
          String s2 = definition.getDocumentBaseURI();
          Definition definition1 = null;
          InputStream inputstream = null;
          InputSource inputsource = null;
          URL url = null;
          if (loc != null)
          {
            inputsource = loc.getImportInputSource(s2, s1);
            String s3 = loc.getLatestImportURI();
            definition1 = (Definition) map.get(s3);
          }
          else
          {
            URL url1 = s2 == null ? null : StringUtils.getURL(null, s2);
            url = StringUtils.getURL(url1, s1);
            definition1 = (Definition) map.get(url.toString());
            if (definition1 == null)
            {
              try
              {

                inputstream = url.openStream();
              }
              catch (IOException ex)
              {
                //import1.setLocationURI(null);
                addElementToList(element, import1);
                return import1;
              }
              if (inputstream != null)
                inputsource = new InputSource(inputstream);
            }
          }
          if (definition1 == null)
          {
            if (inputsource == null)
              throw new WSDLException(
                "OTHER_ERROR",
                "Unable to locate imported document at '"
                  + s1
                  + "'"
                  + (s2 != null ? ", relative to '" + s2 + "'." : "."));
            Document document = null;
            try
            {
              document = getDocument(inputsource, s1);
            }
            catch (WSDLException ex)
            {
              addElementToList(element, import1);
              return import1;
            }
            if (inputstream != null)
              inputstream.close();
            Element element2 = document.getDocumentElement();
            if (QNameUtils.matches(Constants.Q_ELEM_DEFINITIONS, element2))
            {
              if (verbose)
                System.out.println(
                  "Retrieving document at '"
                    + s1
                    + "'"
                    + (s2 != null ? ", relative to '" + s2 + "'." : "."));
              String s4 =
                loc == null
                  ? url == null
                  ? s1
                  : url.toString() : loc.getLatestImportURI();
              definition1 = readWSDL(s4, element2, map);
            }
            else
            {
              QName qname = QNameUtils.newQName(element2);
              if (Constants.XSD_QNAME_LIST.contains(qname))
              {
                WSDLFactory wsdlfactory =
                  factoryImplName == null
                    ? WSDLFactory.newInstance()
                    : WSDLFactory.newInstance(factoryImplName);
                definition1 = wsdlfactory.newDefinition();
                if (extReg != null)
                  definition1.setExtensionRegistry(extReg);
                String s5 =
                  loc == null
                    ? url == null
                    ? s1
                    : url.toString() : loc.getLatestImportURI();
                definition1.setDocumentBaseURI(s5);
                /* Don't add types element since it doesn't exist.  Adding it causes problems
                 * since it will add a types element for processing that does not exist.
                Types types = definition1.createTypes();
                UnknownExtensibilityElement unknownextensibilityelement =
                	new UnknownExtensibilityElement();
                unknownextensibilityelement.setElement(element2);
                types.addExtensibilityElement(
                	unknownextensibilityelement);
                definition1.setTypes(types);
                */
              }
            }
          }
          if (definition1 != null)
            import1.setDefinition(definition1);
        }
        catch (WSDLException wsdlexception)
        {
          wsdlexception.setLocation(XPathUtils.getXPathExprFromNode(element));
          throw wsdlexception;
        }
        catch (Throwable throwable)
        {
          throw new WSDLException(
            "OTHER_ERROR",
            "Unable to resolve imported document at '" + s1 + "'.",
            throwable);
        }
    }
    for (Element element1 = DOMUtils.getFirstChildElement(element);
      element1 != null;
      element1 = DOMUtils.getNextSiblingElement(element1))
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, element1))
        import1.setDocumentationElement(element1);
      else
        DOMUtils.throwWSDLException(element1);

    return import1;

  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseTypes(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Types parseTypes(Element typesEl, Definition def)
    throws WSDLException
  {
    Types types = super.parseTypes(typesEl, def);

    // Try to add element to list
    addElementToList(typesEl, types);

    return types;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseBinding(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Binding parseBinding(Element bindingEl, Definition def)
    throws WSDLException
  {
    Binding binding = super.parseBinding(bindingEl, def);

    // Try to add element to list
    addElementToList(bindingEl, binding);

    return binding;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseBindingOperation(org.w3c.dom.Element, javax.wsdl.PortType, javax.wsdl.Definition)
   */
  protected BindingOperation parseBindingOperation(
    Element bindingOperationEl,
    PortType portType,
    Definition def)
    throws WSDLException
  {
    BindingOperation bindingOperation = null;

    // The follow try-catch was added to detect when a duplicate operation name was detected
    try
    {
      bindingOperation =
        super.parseBindingOperation(bindingOperationEl, portType, def);
    }

    catch (IllegalArgumentException iae)
    {
      if (iae.getMessage().startsWith("Duplicate"))
      {
        bindingOperation =
          parseBindingOperationWithDuplicateNames(
            bindingOperationEl,
            portType,
            def);
      }

      else
      {
        throw iae;
      }
    }

    // Try to add element to list
    if (bindingOperation != null)
    {
      addElementToList(bindingOperationEl, bindingOperation);
    }

    return bindingOperation;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseBindingInput(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected BindingInput parseBindingInput(
    Element bindingInputEl,
    Definition def)
    throws WSDLException
  {
    BindingInput bindingInput = super.parseBindingInput(bindingInputEl, def);

    // Try to add element to list
    addElementToList(bindingInputEl, bindingInput);

    return bindingInput;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseBindingOutput(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected BindingOutput parseBindingOutput(
    Element bindingOutputEl,
    Definition def)
    throws WSDLException
  {
    BindingOutput bindingOutput =
      super.parseBindingOutput(bindingOutputEl, def);

    // Try to add element to list
    addElementToList(bindingOutputEl, bindingOutput);

    return bindingOutput;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseBindingFault(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected BindingFault parseBindingFault(
    Element bindingFaultEl,
    Definition def)
    throws WSDLException
  {
    BindingFault bindingFault = super.parseBindingFault(bindingFaultEl, def);

    // Try to add element to list
    addElementToList(bindingFaultEl, bindingFault);

    return bindingFault;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseMessage(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Message parseMessage(Element msgEl, Definition def)
    throws WSDLException
  {
    Message msg = super.parseMessage(msgEl, def);

    // Try to add element to list
    addElementToList(msgEl, msg);

    return msg;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parsePart(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Part parsePart(Element partEl, Definition def) throws WSDLException
  {
    //Part part = super.parsePart(partEl, def);

    Part part = def.createPart();
    String name = DOMUtils.getAttribute(partEl, Constants.ATTR_NAME);

    // WS-I: The try-catch was added for WSI2416
    QName elementName;

    try
    {
      elementName =
        DOMUtils.getQualifiedAttributeValue(
          partEl,
          Constants.ATTR_ELEMENT,
          Constants.ELEM_MESSAGE,
          false);
    }

    catch (WSDLException we)
    {
      String prefixedValue =
        DOMUtils.getAttribute(partEl, Constants.ATTR_ELEMENT);
      int index = prefixedValue.indexOf(':');
      String prefix = (index != -1) ? prefixedValue.substring(0, index) : null;
      String localPart = prefixedValue.substring(index + 1);

      elementName = new QName(localPart);
    }

    QName typeName =
      DOMUtils.getQualifiedAttributeValue(
        partEl,
        Constants.ATTR_TYPE,
        Constants.ELEM_MESSAGE,
        false);

    if (name != null)
    {
      part.setName(name);
    }

    if (elementName != null)
    {
      part.setElementName(elementName);
    }

    if (typeName != null)
    {
      part.setTypeName(typeName);
    }

    Element tempEl = DOMUtils.getFirstChildElement(partEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        part.setDocumentationElement(tempEl);
      }
      else
      {
        DOMUtils.throwWSDLException(tempEl);
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    Map extensionAttributes = part.getExtensionAttributes();

    extensionAttributes.putAll(getPartAttributes(partEl, def));

    // Need to do something here to locate part definition.

    // Try to add element to list
    addElementToList(partEl, part);

    return part;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parsePortType(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected PortType parsePortType(Element portTypeEl, Definition def)
    throws WSDLException
  {
    PortType portType = super.parsePortType(portTypeEl, def);

    // Try to add element to list
    addElementToList(portTypeEl, portType);

    return portType;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseOperation(org.w3c.dom.Element, javax.wsdl.PortType, javax.wsdl.Definition)
   */
  protected Operation parseOperation(
    Element opEl,
    PortType portType,
    Definition def)
    throws WSDLException
  {
    Operation op = super.parseOperation(opEl, portType, def);

    // Try to add element to list
    addElementToList(opEl, op);

    return op;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseService(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Service parseService(Element serviceEl, Definition def)
    throws WSDLException
  {
    Service service = super.parseService(serviceEl, def);

    // Try to add element to list
    addElementToList(serviceEl, service);

    return service;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parsePort(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Port parsePort(Element portEl, Definition def) throws WSDLException
  {
    Port port = super.parsePort(portEl, def);

    // Try to add element to list
    addElementToList(portEl, port);

    return port;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseExtensibilityElement(java.lang.Class, org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected ExtensibilityElement parseExtensibilityElement(
    Class parentType,
    Element el,
    Definition def)
    throws WSDLException
  {
    ExtensibilityElement extElement =
      super.parseExtensibilityElement(parentType, el, def);

    // Try to add element to list
    addElementToList(el, extElement);

    return extElement;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseInput(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Input parseInput(Element inputEl, Definition def)
    throws WSDLException
  {
    Input input = super.parseInput(inputEl, def);

    // Try to add element to list
    addElementToList(inputEl, input);

    return input;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseOutput(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Output parseOutput(Element outputEl, Definition def)
    throws WSDLException
  {
    Output output = super.parseOutput(outputEl, def);

    // Try to add element to list
    addElementToList(outputEl, output);

    return output;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#parseFault(org.w3c.dom.Element, javax.wsdl.Definition)
   */
  protected Fault parseFault(Element faultEl, Definition def)
    throws WSDLException
  {
    Fault fault = super.parseFault(faultEl, def);

    // Try to add element to list
    addElementToList(faultEl, fault);

    return fault;
  }

  /* (non-Javadoc)
   * @see com.ibm.wsdl.xml.WSDLReaderImpl#getDocument(org.xml.sax.InputSource, java.lang.String)
   */
  protected Document getDocument(InputSource inputSource, String desc)
    throws WSDLException
  {
    ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
    try
	{
      Thread.currentThread().setContextClassLoader(WSDLReaderImpl.class.getClassLoader());   	
	
  	  //DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilderFactory factory =
        new org.eclipse.wst.wsi.internal.core.xml.jaxp.DocumentBuilderFactoryImpl();

      factory.setNamespaceAware(true);
      factory.setValidating(false);

      DocumentBuilder builder = factory.newDocumentBuilder();
      Document doc = builder.parse(inputSource);

      return doc;
    }
    catch (Throwable t)
    {
      throw new WSDLException(
        WSDLException.PARSER_ERROR,
        "Problem parsing '" + desc + "'.",
        t);
    }
    finally
    { 
      Thread.currentThread().setContextClassLoader(currentLoader);
    }    
  }

  /**
   * Get element list.
   * @return the element list.
   */
  public WSDLElementList getElementList()
  {
    return this.wsdlElementList;
  }

  /** 
   * Add WSDL element to element list.
   */
  private void addElementToList(Element element, Object wsdlElement)
  {
    ElementLocation elementLocation = null;

    try
    {
      // See if the element object is an instanceof org.apache.xerces.dom.ElementImpl
      ElementImpl elementImpl = (ElementImpl) element;

      // If it is, then get the element location information
      elementLocation =
        (ElementLocation) elementImpl.getUserData(ElementLocation.KEY_NAME);

      // Add it to the list
      this.wsdlElementList.addElement(wsdlElement, elementLocation);
    }

    catch (ClassCastException cce)
    {
      // ADD: Should we add the element with a null or zero location?
    }
  }

  /**
   * This method is used when a WSDL document contains duplicate operation names.
   * It is the same as the original parseBindingOperation method, except that it will
   * just find the first operation that matches instead of throwing an exception.
   */
  private BindingOperation parseBindingOperationWithDuplicateNames(
    Element bindingOperationEl,
    PortType portType,
    Definition def)
    throws WSDLException
  {
    BindingOperation bindingOperation = def.createBindingOperation();
    String name =
      DOMUtils.getAttribute(bindingOperationEl, Constants.ATTR_NAME);

    if (name != null)
    {
      bindingOperation.setName(name);
    }

    Element tempEl = DOMUtils.getFirstChildElement(bindingOperationEl);

    while (tempEl != null)
    {
      if (QNameUtils.matches(Constants.Q_ELEM_DOCUMENTATION, tempEl))
      {
        bindingOperation.setDocumentationElement(tempEl);
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_INPUT, tempEl))
      {
        bindingOperation.setBindingInput(parseBindingInput(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_OUTPUT, tempEl))
      {
        bindingOperation.setBindingOutput(parseBindingOutput(tempEl, def));
      }
      else if (QNameUtils.matches(Constants.Q_ELEM_FAULT, tempEl))
      {
        bindingOperation.addBindingFault(parseBindingFault(tempEl, def));
      }
      else
      {
        bindingOperation.addExtensibilityElement(
          parseExtensibilityElement(BindingOperation.class, tempEl, def));
      }

      tempEl = DOMUtils.getNextSiblingElement(tempEl);
    }

    if (portType != null)
    {
      BindingInput bindingInput = bindingOperation.getBindingInput();
      BindingOutput bindingOutput = bindingOperation.getBindingOutput();
      String inputName = (bindingInput != null ? bindingInput.getName() : null);
      String outputName =
        (bindingOutput != null ? bindingOutput.getName() : null);

      //Operation op = portType.getOperation(name, inputName, outputName);
      // Get all operations, and then find the first one that matches
      Operation op = null, checkOperation;
      Iterator iterator = portType.getOperations().iterator();
      while (iterator.hasNext() && op == null)
      {
        // Get the next operation
        checkOperation = (Operation) iterator.next();

        // Get the operation name, input name, and output name
        String checkName = checkOperation.getName();
        String checkInputName =
          (checkOperation.getInput() == null
            ? null
            : checkOperation.getInput().getName());
        String checkOutputName =
          (checkOperation.getOutput() == null
            ? null
            : checkOperation.getOutput().getName());

        // If the names match, then that operation
        if ((checkName != null && checkName.equals(name))
          && ((checkInputName != null && checkInputName.equals(inputName))
            || (checkInputName == null && inputName == null))
          && ((checkOutputName != null && checkOutputName.equals(outputName))
            || (checkOutputName == null && outputName == null)))
        {
          op = checkOperation;
        }
      }

      if (op == null)
      {
        op = def.createOperation();
        op.setName(name);
        portType.addOperation(op);
      }

      bindingOperation.setOperation(op);
    }

    return bindingOperation;
  }

}
