/*******************************************************************************
 * Copyright (c) 2002-2005 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.wsi.internal.core.profile.impl;

import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
import org.eclipse.wst.wsi.internal.WSITestToolsEclipseProperties;
import org.eclipse.wst.wsi.internal.WSITestToolsProperties;
import org.eclipse.wst.wsi.internal.core.WSIConstants;
import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.profile.EntryTypeList;
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.ProfileAssertionsReader;
import org.eclipse.wst.wsi.internal.core.profile.TestAssertion;
import org.eclipse.wst.wsi.internal.core.util.ArtifactType;
import org.eclipse.wst.wsi.internal.core.util.Utils;
import org.eclipse.wst.wsi.internal.core.xml.XMLUtils;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * This class ...
 * 
 * @version 1.0.1
 * @author Peter Brittenham  (peterbr@us.ibm.com)
 */
public class ProfileAssertionsReaderImpl implements ProfileAssertionsReader
{
  /**
   * Profile assertions.
   */
  protected ProfileAssertions profileAssertions;

  /**
   * ReportArtifact list.
   */
  protected TreeMap artifactList = new TreeMap();

  /**
   * Create new reader.
   */
  public ProfileAssertionsReaderImpl()
  {
  }

  /* (non-Javadoc)
   * @see org.wsi.test.profile.ProfileAssertionsReader#readProfileAssertions(String)
   */
  public ProfileAssertions readProfileAssertions(String assertionsURI)
    throws WSIException
  {
    return readProfileAssertions(new InputSource(assertionsURI));
  }

  /* (non-Javadoc)
   * @see org.wsi.test.profile.ProfileAssertionsReader#readProfileAssertions(Reader)
   */
  public ProfileAssertions readProfileAssertions(Reader reader)
    throws WSIException
  {
    return readProfileAssertions(new InputSource(reader));
  }

  /**
   * Read profile assertions.
   */
  private ProfileAssertions readProfileAssertions(InputSource inputSource)
    throws WSIException
  {
    // Create profile assertions
    profileAssertions = new ProfileAssertionsImpl();

    // Profile parts are put into a vector
    artifactList = new TreeMap();

    try
    {
      // Create xml reader
      XMLReader reader = XMLUtils.getXMLReader();

      // Set content handler to inner class
      reader.setContentHandler(new ProfileAssertionsHandler());
      
      if(WSITestToolsProperties.getEclipseContext())
      {
    	  EntityResolver resolver = new EntityResolver(){

			public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
				URIResolver resolver = WSITestToolsEclipseProperties.getURIResolver();
				String uri = resolver.resolve("", publicId, systemId);
				String physicalLocation = resolver.resolvePhysicalLocation("", publicId, uri);
				InputSource is = null;
				try
				{
					URL url = new URL(physicalLocation);
					is = new InputSource(uri);
					is.setByteStream(url.openStream());
				}
				catch(Exception e)
				{
					// Do nothing if opening the stream fails.
				}
				return is;
			}
    		  
    	  };
    	  reader.setEntityResolver(resolver);
      }
      // Parse profile definition file
      reader.parse(inputSource);
    }

    catch (Exception e)
    {
      throw new WSIException("Could not read and parse profile definition.", e);
    }
    finally
    {
      //Check to see if the version of test asssertion document is supported
      if (!Utils.isValidProfileTADVersion(profileAssertions))
      {
    	String tadVersion = profileAssertions.getTADVersion();
    	if(tadVersion != null)
    	{
    	  String tadName = profileAssertions.getTADName();
          throw new WSIException(
          "\nVersion "
            + tadVersion
            + " of the \""
            + tadName
            + "\"\n"
            + "document is not compatible with this version of"
            + "\n"
            + "the test tools.");
    	}
    	else
    	{
    	  throw new WSIException("WS-I validation was unable to run. Unable to read the test assertion document.");
    	}
      }
    }

    // The assertions from the TAD are reordered for purposes of processing. All
    // assertions of an artifact are reordered such that prerequisites occur
    // before the assertions they prereq. The assumption is that  prerequisites do
    // not cross artifact types.
    //
    Iterator it = artifactList.keySet().iterator();
    // for each artifact type do reordering assertion 
    while (it.hasNext())
    {
      ProfileArtifact art = (ProfileArtifact) artifactList.get(it.next());
      // result list of the reordering assertions 
      LinkedList res = new LinkedList();
      Iterator it2 = art.getTestAssertionList().iterator();
      // sort the artifact assertions into result list 
      while (it2.hasNext())
      {
        // call for each assertion , 
        // if the assertion has the prereq, the prereq will added first into res list
        sortTestAssertions(art, (TestAssertion) it2.next(), res);
      }
      // replace the original assertions list to the prereq reordering assertions list
      art.getTestAssertionList().clear();
      art.getTestAssertionList().addAll(res);
    }
    // Put the profile parts into the profile definition
    profileAssertions.setArtifactList(artifactList);

    return profileAssertions;
  }
  
  /* (non-Javadoc)
   * @see org.wsi.test.document.DocumentReader#getLocation()
   */
  public String getLocation()
  {
    return null;
  }

  /* (non-Javadoc)
   * @see org.wsi.test.document.DocumentReader#setLocation(String)
   */
  public void setLocation(String documentURI)
  {
  }

  /**
   * Recursive walk to order assertions so that assertions are 
   * processed following the ones that prereq them.
   * If assertion has prereq, then add it to the result list first.
   *  
   * @param art profile artifact for call @link ProfileArtifact#getTestAssertion(String)
   * @param asrt test assertion
   * @param list result list to sort
   */
  private void sortTestAssertions(ProfileArtifact art, TestAssertion asrt, List list)
  {
    // if assertion is null or does not exist, then exit
    if((asrt == null) || list.contains(asrt)) 
      return;
    
    // if it has not prereq, add the asertion and exit
    if(asrt.getPrereqIdList().isEmpty()) 
    {
      list.add(asrt);
      return;
    }
    // get list prereq assertion and reqursive call sortTestAssertions this each    
    Iterator it = asrt.getPrereqIdList().iterator();
    while(it.hasNext()) {
      String id = (String) it.next();
      sortTestAssertions(art, art.getTestAssertion(id), list);
    }
    list.add(asrt);
  }

  /**
   * Inner class: ProfileAssertionsHandler
   */
  class ProfileAssertionsHandler extends DefaultHandler
  {
    private ProfileArtifact artifact = profileAssertions.createArtifact();
    private StringBuffer context = null;
    private StringBuffer assertionDescription = null;
    private StringBuffer failureMessage = null;
    private StringBuffer failureDetailDescription = null;
    private StringBuffer detailDescription = null;
    private StringBuffer testAssertionId = null;
    private String currentElement = null;
    private TestAssertion testAssertion = null;
    private StringBuffer logInput = null;
    private StringBuffer wsdlInput = null;
    private EntryTypeList entryTypeList = null;

    // Process start element event
    public void startElement(
      String namespaceURI,
      String localName,
      String qName,
      Attributes atts)
    {
      if (namespaceURI != null
        && (namespaceURI.equals(WSIConstants.NS_URI_WSI_ASSERTIONS_2003)
        ||  namespaceURI.equals(WSIConstants.NS_URI_WSI_ASSERTIONS)))
      {
        // Save element name
        currentElement = localName;

        // <artifact>
        if (localName.equals(WSIConstants.ELEM_ARTIFACT))
        {
          // Create a new profile artifact object
          artifact = profileAssertions.createArtifact();

          // Set type
          artifact.setType(
            ArtifactType.newArtifactType(
              atts.getValue(WSIConstants.ATTR_TYPE)));

          // ADD: Get specification list

          // Add artifact to list of artifact list
          artifactList.put(artifact.getType().getTypeName(), artifact);
        }

        // <testAssertion>
        else if (localName.equals(WSIConstants.ELEM_TEST_ASSERTION))
        {
          // Create test assertion
          testAssertion = new TestAssertionImpl();

          // Get attribute values
          String id = atts.getValue("", WSIConstants.ATTR_ID);
          testAssertion.setId(id);
          testAssertion.setType(atts.getValue("", WSIConstants.ATTR_TYPE));
          testAssertion.setEntryTypeName(
            atts.getValue("", WSIConstants.ATTR_ENTRY_TYPE));
          
          // if assertion already checked then disable it
          if (alreadyChecked(id))
        	  testAssertion.setEnabled(false);
          else
        	  testAssertion.setEnabled(Boolean.valueOf(atts.getValue("", WSIConstants.ATTR_ENABLED)).booleanValue());

          // Add test assertion to artifact
          artifact.addTestAssertion(testAssertion);
        }

        // <context>
        else if (localName.equals(WSIConstants.ELEM_CONTEXT))
        {
          context = new StringBuffer();
        }

        // <assertionDescription>
        else if (localName.equals(WSIConstants.ELEM_ASSERTION_DESCRIPTION))
        {
          assertionDescription = new StringBuffer();
        }

        // <failureMessage>
        else if (localName.equals(WSIConstants.ELEM_FAILURE_MESSAGE))
        {
          failureMessage = new StringBuffer();
        }

        // <failureDetailDescription>
        else if (localName.equals(WSIConstants.ELEM_FAILURE_DETAIL_DESCRIPTION))
        {
          failureDetailDescription = new StringBuffer();
        }

        // <detailDescription>
        else if (localName.equals(WSIConstants.ELEM_DETAIL_DESCRIPTION))
        {
          detailDescription = new StringBuffer();
        }

        // <testAssertionID>
        else if (localName.equals(WSIConstants.ELEM_TEST_ASSERTION_ID))
        {
          testAssertionId = new StringBuffer();
        }

        // <additionalEntryTypeList>
        else if (
          localName.equals(WSIConstants.ELEM_ADDITIONAL_ENTRY_TYPE_LIST))
        {
          // Create entry type list
          entryTypeList = new EntryTypeListImpl();
        }

        // <messageInput>
        else if (localName.equals(WSIConstants.ELEM_MESSAGE_INPUT))
        {
          logInput = new StringBuffer();
        }

        // <wsdlInput>
        else if (localName.equals(WSIConstants.ELEM_WSDL_INPUT))
        {
          wsdlInput = new StringBuffer();
        }
        // <profileAssertions>
        else if (localName.equals(WSIConstants.ELEM_PROFILE_ASSERTIONS))
        {
          profileAssertions.setTADName(
            atts.getValue("", WSIConstants.ATTR_NAME));
          profileAssertions.setTADVersion(
            atts.getValue("", WSIConstants.ATTR_VERSION));
        }

        /* REMOVE:     
        // <uddiInput>
        else if (localName.equals(WSIConstants.ELEM_UDDI_INPUT)) {
          uddiInput = new StringBuffer();
        } 
        */
      }
    } // END startElement

    public void endElement(String namespaceURI, String localName, String qname)
    {
      // If this is the profile namespace, then check for and process selected elements
      if (namespaceURI != null
        && (namespaceURI.equals(WSIConstants.NS_URI_WSI_ASSERTIONS_2003)
        || namespaceURI.equals(WSIConstants.NS_URI_WSI_ASSERTIONS)))
      {
        // <context>
        if (localName.equals(WSIConstants.ELEM_CONTEXT))
        {
          // Set context in test assertion
          testAssertion.setContext(context.toString());
          context = null;
        }

        // <assertionDescription>
        else if (localName.equals(WSIConstants.ELEM_ASSERTION_DESCRIPTION))
        {
          // Set assertion description in test assertion
          testAssertion.setAssertionDescription(
            assertionDescription.toString());
          assertionDescription = null;
        }

        // <failureMessage>
        else if (localName.equals(WSIConstants.ELEM_FAILURE_MESSAGE))
        {
          // Set failure message in test assertion
          testAssertion.setFailureMessage(failureMessage.toString());
          failureMessage = null;
        }

        // <failureDetailDescription>
        else if (localName.equals(WSIConstants.ELEM_FAILURE_DETAIL_DESCRIPTION))
        {
          // Set failure detail description in test assertion
          testAssertion.setFailureDetailDescription(
            failureDetailDescription.toString());
          failureDetailDescription = null;
        }

        // <detailDescription>
        else if (localName.equals(WSIConstants.ELEM_DETAIL_DESCRIPTION))
        {
          // Set detail description in test assertion
          testAssertion.setDetailDescription(detailDescription.toString());
          detailDescription = null;
        }

        // <testAssertionID>
        else if (localName.equals(WSIConstants.ELEM_TEST_ASSERTION_ID))
        {
          // Set test assertion id in prereq list
          testAssertion.addPrereqId(testAssertionId.toString());
          testAssertionId = null;
        }

        // <addtionalEntryTypeList>
        else if (
          localName.equals(WSIConstants.ELEM_ADDITIONAL_ENTRY_TYPE_LIST))
        {
          // Set target list
          testAssertion.setAdditionalEntryTypeList(entryTypeList);
          entryTypeList = null;
        }

        // <messageInput>
        else if (localName.equals(WSIConstants.ELEM_MESSAGE_INPUT))
        {
          // Set test assertion id in prereq list
          entryTypeList.setLogInput(logInput.toString());
          logInput = null;
        }

        // <wsdlInput>
        else if (localName.equals(WSIConstants.ELEM_WSDL_INPUT))
        {
          // Set test assertion id in prereq list
          entryTypeList.setWSDLInput(wsdlInput.toString());
          wsdlInput = null;
        }

        // <profileAssertions>
        else if (localName.equals(WSIConstants.ELEM_PROFILE_ASSERTIONS))
        {
          // a no-op
        }

        /* REMOVE:
        // <uddiInput>
        else if (localName.equals(WSIConstants.ELEM_UDDI_INPUT)) {
          // Set test assertion id in prereq list
           entryTypeList.setUDDIInput(uddiInput.toString());         
          uddiInput = null;
        }
        */
      }
    } // END endElement

    public void characters(char[] ch, int start, int length)
    {
      // <context>
      if ((context != null)
        && (currentElement.equals(WSIConstants.ELEM_CONTEXT)))
      {
        context.append(ch, start, length);
      }

      // <assertionDescription>
      else if (
        (assertionDescription != null)
          && (currentElement.equals(WSIConstants.ELEM_ASSERTION_DESCRIPTION)))
      {
        assertionDescription.append(ch, start, length);
      }

      // <failureMessage>
      else if (
        (failureMessage != null)
          && (currentElement.equals(WSIConstants.ELEM_FAILURE_MESSAGE)))
      {
        failureMessage.append(ch, start, length);
      }

      // <failureDetailDescription>
      else if (
        (failureDetailDescription != null) && (
          currentElement.equals(WSIConstants.ELEM_FAILURE_DETAIL_DESCRIPTION)))
      {
        failureDetailDescription.append(ch, start, length);
      }

      // <detailDescription>
      else if (
        (detailDescription != null)
          && (currentElement.equals(WSIConstants.ELEM_DETAIL_DESCRIPTION)))
      {
        detailDescription.append(ch, start, length);
      }

      // <testAssertionID>
      else if (
        (testAssertionId != null)
          && (currentElement.equals(WSIConstants.ELEM_TEST_ASSERTION_ID)))
      {
        testAssertionId.append(ch, start, length);
      }

      // <messageInput>
      else if (
        (logInput != null)
          && (currentElement.equals(WSIConstants.ELEM_MESSAGE_INPUT)))
      {
        logInput.append(ch, start, length);
      }

      // <wsdlInput>
      else if (
        (wsdlInput != null)
          && (currentElement.equals(WSIConstants.ELEM_WSDL_INPUT)))
      {
        wsdlInput.append(ch, start, length);
      }

      /* REMOVE:
      // <uddiInput>
      else if ((uddiInput != null) && (currentElement.equals(WSIConstants.ELEM_UDDI_INPUT))) {
        uddiInput.append(ch, start, length);
      }
      */
    }
  }

  /**
   * NOTE that this api assumes that base wsdl validator has already validated
   * the wsdl document and corresponding schemas against the wsdl 1.1 specification.
   * Note also that there are a number of duplicate checks between the base validator
   * and the ws-i validator. Since some of these checks are cpu intensive, we disable 
   * those assertions here. 
   *
   * Returns true if the assertion has already been checked by the base validator. 
   * @param testAssertion
   * @return true if the assertion has already been checked by the base validator. 
   */
  protected boolean alreadyChecked(String id)
  {
	 boolean result = false;
	 if (id != null)
	 {
       result = (id.equals("BP2110") ||
    		   	 id.equals("BP2115") ||
		         id.equals("BP2417") ||
		         id.equals("BP2114") ||
		         id.equals("BP2123") ||
		         id.equals("SSBP2209") ||
		         id.equals("AP2209"));
	 }
	 return result;
}


}
