/*******************************************************************************
 * Copyright (c) 2001, 2008 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 Corporation - initial API and implementation
 *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
 *******************************************************************************/

package org.eclipse.wst.xml.core.internal.validation;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.ConnectException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.msg.XMLMessageFormatter;
import org.apache.xerces.parsers.XIncludeAwareParserConfiguration;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.validation.ValidationResult;
import org.eclipse.wst.xml.core.internal.Logger;
import org.eclipse.wst.xml.core.internal.validation.core.LazyURLInputStream;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.helpers.DefaultHandler;

/**
 * This class performs validation using a xerces sax parser.  
 * Here's a quick overview of the details : 
 *   - an ErrorHandler is used to collect errors into a list (so they may be displayed by the UI)
 *   - an EntityResolver is used along with the xerces "external-schemaLocation" property to implement XML Catalog support
 */
public class XMLValidator
{
  protected URIResolver uriResolver = null;
  protected Hashtable ingoredErrorKeyTable = new Hashtable();
  protected Set adjustLocationErrorKeySet = new TreeSet();

  protected static final String IGNORE_ALWAYS = "IGNORE_ALWAYS"; //$NON-NLS-1$
  protected static final String IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL = "IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL"; //$NON-NLS-1$
  protected static final String PREMATURE_EOF = "PrematureEOF"; //$NON-NLS-1$
  protected static final String ROOT_ELEMENT_TYPE_MUST_MATCH_DOCTYPEDECL = "RootElementTypeMustMatchDoctypedecl"; //$NON-NLS-1$
  protected static final String MSG_ELEMENT_NOT_DECLARED = "MSG_ELEMENT_NOT_DECLARED"; //$NON-NLS-1$
  
  // WTP XML validator specific key.
  protected static final String NO_GRAMMAR_FOUND = "NO_GRAMMAR_FOUND"; //$NON-NLS-1$
  
  private static final String FILE_NOT_FOUND_KEY = "FILE_NOT_FOUND"; //$NON-NLS-1$

  /**
   * Constructor.
   */
  public XMLValidator()
  {                          
    // Here we add some error keys that we need to filter out when we're validation 
    // against a DTD without any element declarations.       
    ingoredErrorKeyTable.put(PREMATURE_EOF, IGNORE_ALWAYS);
    ingoredErrorKeyTable.put(ROOT_ELEMENT_TYPE_MUST_MATCH_DOCTYPEDECL, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
    ingoredErrorKeyTable.put(MSG_ELEMENT_NOT_DECLARED, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
    
    // Here we add some error keys that we need to adjust the location information for.
    // The location information will be adjusted to place the message on the line of the starting
    // element instead of on the line of the closing element.
    adjustLocationErrorKeySet.add("MSG_CONTENT_INVALID");
    adjustLocationErrorKeySet.add("MSG_CONTENT_INCOMPLETE");
    adjustLocationErrorKeySet.add("cvc-complex-type.2.4.b");
    adjustLocationErrorKeySet.add("cvc-complex-type.2.3");
  }

  /**
   * Set the URI Resolver to use.
   * 
   * @param uriResolver The URI Resolver to use.
   */
  public void setURIResolver(URIResolver uriResolver)
  {
    this.uriResolver = uriResolver;
    //entityResolver = new MyEntityResolver(uriResolver);
  }

 
  /**
   * Create an XML Reader.
   * 
   * @return The newly created XML reader or null if unsuccessful.
   * @throws Exception
   */
  protected XMLReader createXMLReader(final XMLValidationInfo valinfo, XMLEntityResolver entityResolver) throws Exception
  {     
    XMLReader reader = null;
    // move to Xerces-2... add the contextClassLoader stuff
    ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
    try
    {
      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
      MyStandardParserConfiguration configuration = new MyStandardParserConfiguration(valinfo);
      reader = new org.apache.xerces.parsers.SAXParser(configuration)
      {
    	private XMLLocator locator = null;
    	
        /* (non-Javadoc)
         * @see org.apache.xerces.parsers.AbstractSAXParser#startDocument(org.apache.xerces.xni.XMLLocator, java.lang.String, org.apache.xerces.xni.NamespaceContext, org.apache.xerces.xni.Augmentations)
         */
        public void startDocument(org.apache.xerces.xni.XMLLocator theLocator, java.lang.String encoding, NamespaceContext nscontext, org.apache.xerces.xni.Augmentations augs) 
        {
          locator = theLocator;
          valinfo.setXMLLocator(theLocator);
          super.startDocument(theLocator, encoding, nscontext, augs); 
        }

        /* (non-Javadoc)
         * @see org.apache.xerces.parsers.AbstractSAXParser#startElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations)
         */
        public void startElement(QName arg0, XMLAttributes arg1, Augmentations arg2) throws XNIException 
        {
          valinfo.getStartElementLocations().push(new LocationCoordinate(locator.getLineNumber(), locator.getColumnNumber()));
		  super.startElement(arg0, arg1, arg2);
		}
        
		/* (non-Javadoc)
		 * @see org.apache.xerces.parsers.AbstractSAXParser#endElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.Augmentations)
		 */
		public void endElement(QName arg0, Augmentations arg1) throws XNIException {
			super.endElement(arg0, arg1);
			valinfo.getStartElementLocations().pop();
		}
      };

      reader.setFeature("http://apache.org/xml/features/continue-after-fatal-error", false); //$NON-NLS-1$
      reader.setFeature("http://xml.org/sax/features/namespace-prefixes", valinfo.isNamespaceEncountered()); //$NON-NLS-1$
      reader.setFeature("http://xml.org/sax/features/namespaces", valinfo.isNamespaceEncountered());               //$NON-NLS-1$
      reader.setFeature("http://xml.org/sax/features/validation", valinfo.isGrammarEncountered());  //$NON-NLS-1$
      reader.setFeature("http://apache.org/xml/features/validation/schema", valinfo.isGrammarEncountered()); //$NON-NLS-1$
   	  reader.setFeature("http://apache.org/xml/features/xinclude", valinfo.isUseXInclude()); //$NON-NLS-1$      
      reader.setContentHandler(new DefaultHandler()
      {
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
          valinfo.getErrorCustomizationManager().startElement(uri, localName);                    
        }
        
        public void endElement(String uri, String localName, String qName) throws SAXException {
          valinfo.getErrorCustomizationManager().endElement(uri, localName);
        }
      });      
      
      // MH make sure validation works even when a customer entityResolver is note set (i.e. via setURIResolver())
      if (entityResolver != null)
      {  
        reader.setProperty("http://apache.org/xml/properties/internal/entity-resolver", entityResolver); //$NON-NLS-1$
      }  
      reader.setProperty("http://xml.org/sax/properties/declaration-handler", new MyDeclHandler());      //$NON-NLS-1$
    } 
    catch(Exception e)
    { 
      Logger.logException(e);
      //e.printStackTrace();
    }
    finally
    {
      Thread.currentThread().setContextClassLoader(prevClassLoader);
    }
    return reader;
  }  

  /**
   * Validate the file located at the given URI.
   * 
   * @param uri The URI of the file to validate.
   * @return Returns an XML validation report.
   */
  public XMLValidationReport validate(String uri)
  {
    return validate(uri, null, new XMLValidationConfiguration());  
  }

  final String createStringForInputStream(InputStream inputStream)
  {
    // Here we are reading the file and storing to a stringbuffer.
    StringBuffer fileString = new StringBuffer();
    try
    {
      InputStreamReader inputReader = new InputStreamReader(inputStream, "UTF-8");
      BufferedReader reader = new BufferedReader(inputReader);
      char[] chars = new char[1024];
      int numberRead = reader.read(chars);
      while (numberRead != -1)
      {
        fileString.append(chars, 0, numberRead);
        numberRead = reader.read(chars);
      }
    }
    catch (Exception e)
    {
      //TODO: log error message
      //e.printStackTrace();
    }
    return fileString.toString();
  }
  /**
   * Validate the inputStream
   * 
   * @param uri The URI of the file to validate.
   * @param the inputStream of the file to validate
   * @return Returns an XML validation report.
   */
  public XMLValidationReport validate(String uri, InputStream inputStream)
  {
	return validate(uri, inputStream, new XMLValidationConfiguration());
  }
  /**
   * Validate the inputStream
   * 
   * @param uri 
   * 		The URI of the file to validate.
   * @param inputstream
   * 		The inputStream of the file to validate
   * @param configuration
   * 		A configuration for this validation session.
   * @return 
   * 		Returns an XML validation report.
   */
  public XMLValidationReport validate(String uri, InputStream inputStream, XMLValidationConfiguration configuration)
  {
    return validate(uri, inputStream, configuration, null);  
  }
 
  /**
   * Validate the inputStream
   * 
   * @param uri 
   *    The URI of the file to validate.
   * @param inputstream
   *    The inputStream of the file to validate
   * @param configuration
   *    A configuration for this validation session.
   * @param result
   *    The validation result
   * @return 
   *    Returns an XML validation report.
   */
  public XMLValidationReport validate(String uri, InputStream inputStream, XMLValidationConfiguration configuration, ValidationResult result)
  {
    String grammarFile = "";
    Reader reader1 = null; // Used for the preparse.
    Reader reader2 = null; // Used for validation parse.
    
    if (inputStream != null)
    {  
      String string = createStringForInputStream(inputStream);
      reader1 = new StringReader(string);
      reader2 = new StringReader(string);
    } 
        
    XMLValidationInfo valinfo = new XMLValidationInfo(uri);
    MyEntityResolver entityResolver = new MyEntityResolver(uriResolver); 
    ValidatorHelper helper = new ValidatorHelper(); 
    try
    {  
        helper.computeValidationInformation(uri, reader1, uriResolver);
        valinfo.setDTDEncountered(helper.isDTDEncountered);
        valinfo.setElementDeclarationCount(helper.numDTDElements);
        valinfo.setNamespaceEncountered(helper.isNamespaceEncountered);
        valinfo.setGrammarEncountered(helper.isGrammarEncountered);
        
        XMLReader reader = createXMLReader(valinfo, entityResolver);
        XMLErrorHandler errorhandler = new XMLErrorHandler(valinfo);
        reader.setErrorHandler(errorhandler);
        
        InputSource inputSource = new InputSource(uri);
        inputSource.setCharacterStream(reader2);
        reader.parse(inputSource);   
        if(configuration.getIntFeature(XMLValidationConfiguration.INDICATE_NO_GRAMMAR) > 0 && 
        		valinfo.isValid() && !helper.isGrammarEncountered)
        {
          if(configuration.getIntFeature(XMLValidationConfiguration.INDICATE_NO_GRAMMAR) == 1)
            valinfo.addWarning(XMLValidationMessages._WARN_NO_GRAMMAR, 1, 0, uri, NO_GRAMMAR_FOUND, null);
          else // 2
              valinfo.addError(XMLValidationMessages._WARN_NO_GRAMMAR, 1, 0, uri, NO_GRAMMAR_FOUND, null);
        }

        if (helper.isDTDEncountered)
          grammarFile = entityResolver.getLocation();
        else
          grammarFile = helper.schemaLocationString;
    }
    catch (SAXParseException saxParseException)
    {
      // These errors are caught by the error handler.
      //addValidationMessage(valinfo, saxParseException);
    }                 
    catch (IOException ioException)
    {
      addValidationMessage(valinfo, ioException);
    }                 
    catch (Exception exception)
    {  
    	Logger.logException(exception.getLocalizedMessage(), exception);
    }

    // Now set up the dependencies
    // Wrap with try catch so that if something wrong happens, validation can
    // still proceed as before
    if (result != null)
    {
      try
      {
        IResource resource = getWorkspaceFileFromLocation(grammarFile);
        ArrayList resources = new ArrayList();
        if (resource != null)
          resources.add(resource);
        result.setDependsOn((IResource [])resources.toArray(new IResource [0]));
      }
      catch (Exception e)
      {
        Logger.logException(e.getLocalizedMessage(), e);
      }
    }
    
    return valinfo;
       
  }

  /**
   * Add a validation message to the specified list.
   * 
   * @param valinfo The validation info object to add the error to.
   * @param exception The exception that contains the validation information.
   */
  protected void addValidationMessage(XMLValidationInfo valinfo, IOException exception)
  { 
    String validationMessageStr = exception.getMessage();
	Throwable cause = exception.getCause() != null ? exception.getCause() : exception;
	while(validationMessageStr == null && cause != null){
		String localizedMessage = cause.getLocalizedMessage();
	    cause = cause.getCause();
	    if(cause == null && localizedMessage != null )
	    {
	      validationMessageStr = localizedMessage;
	    }
	}
	
	if (validationMessageStr != null)
    {
      if (cause instanceof FileNotFoundException)
      {
        validationMessageStr = NLS.bind(XMLValidationMessages._UI_PROBLEMS_VALIDATING_FILE_NOT_FOUND, new Object [] { validationMessageStr });
      }
      else if (cause instanceof UnknownHostException)
      {
    	validationMessageStr = NLS.bind(XMLValidationMessages._UI_PROBLEMS_VALIDATING_UNKNOWN_HOST, new Object [] { validationMessageStr });
      }
      else if(cause instanceof ConnectException)
      {
    	validationMessageStr = XMLValidationMessages._UI_PROBLEMS_CONNECTION_REFUSED;
      }
    }

    if (validationMessageStr != null)
    {
      XMLLocator locator = valinfo.getXMLLocator();
      valinfo.addWarning(validationMessageStr, locator != null ? locator.getLineNumber() : 1, locator != null ? locator.getColumnNumber() : 0, valinfo.getFileURI(), FILE_NOT_FOUND_KEY, null);
    }
  }
                                                                    
  /**
   * Add a validation message to the specified list.
   * 
   * @param valinfo The validation info object to add the error to.
   * @param exception The exception that contains the validation information.
   */
  protected void addValidationMessage(XMLValidationInfo valinfo, SAXParseException exception)
  { 
    if (exception.getMessage() != null)
    { 
      valinfo.addError(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), exception.getSystemId());
    }
  }

  
  /**
   * A custom entity resolver that uses the URI resolver specified to resolve entities.
   */
  protected class MyEntityResolver implements XMLEntityResolver 
  {
    private URIResolver uriResolver;
    private String resolvedDTDLocation;
   
    /**
     * Constructor.
     * 
     * @param uriResolver The URI resolver to use with this entity resolver.
     */
    public MyEntityResolver(URIResolver uriResolver)
    {
      this.uriResolver = uriResolver;
    }
    
    /* (non-Javadoc)
     * @see org.apache.xerces.xni.parser.XMLEntityResolver#resolveEntity(org.apache.xerces.xni.XMLResourceIdentifier)
     */
    public XMLInputSource resolveEntity(XMLResourceIdentifier rid) throws XNIException, IOException
    {
      try
      {
        XMLInputSource inputSource = _internalResolveEntity(uriResolver, rid);
        if (inputSource != null)
        {
          resolvedDTDLocation = inputSource.getSystemId();
        }
        return inputSource;
      }
      catch(IOException e)
      {
        //e.printStackTrace();   
      }      
      return null;
    }
   
    public String getLocation()
    {
      return resolvedDTDLocation;
    }
  }
  
  // cs : I've refactored the common SAX based resolution code into this method for use by other validators 
  // (i.e. XML Schema, WSDL etc).   The other approach is maintain a copy for each validator that has
  // identical code.  In any case we should strive to ensure that the validators perform resolution consistently. 
  public static XMLInputSource _internalResolveEntity(URIResolver uriResolver, XMLResourceIdentifier rid) throws  IOException
  {
    XMLInputSource is = null;
    
    if (uriResolver != null)
    {         
      String id = rid.getPublicId();
      if(id == null)
      {
        id = rid.getNamespace();
      }
      
      String location = null;
      if (id != null || rid.getLiteralSystemId() != null)
      {  
        location = uriResolver.resolve(rid.getBaseSystemId(), id, rid.getLiteralSystemId());
      }  
      
      if (location != null)
      {                     
        String physical = uriResolver.resolvePhysicalLocation(rid.getBaseSystemId(), id, location);
        is = new XMLInputSource(rid.getPublicId(), location, location);
        
        // This block checks that the file exists. If it doesn't we need to throw
        // an exception so Xerces will report an error. note: This may not be
        // necessary with all versions of Xerces but has specifically been 
        // experienced with the version included in IBM's 1.4.2 JDK.
        InputStream isTemp = null;
        try
        {
          isTemp = new URL(physical).openStream();
        }
        finally
        {
          if(isTemp != null)
          {
            isTemp.close();
          }
        }
        is.setByteStream(new LazyURLInputStream(physical));      
      }
    }
    return is;    
  }      
  
  /**
   * An error handler to catch errors encountered while parsing the XML document.
   */
  protected class XMLErrorHandler implements org.xml.sax.ErrorHandler
  {

    private final int ERROR = 0;
    private final int WARNING = 1;
    private XMLValidationInfo valinfo;
    
    /**
     * Constructor.
     * 
     * @param valinfo The XML validation info object that will hold the validation messages.
     */
    public XMLErrorHandler(XMLValidationInfo valinfo)
    {
      this.valinfo = valinfo;
    }

    /**
     * Add a validation message with the given severity.
     * 
     * @param exception The exception that contains the message.
     * @param severity The severity of the message.
     */
    
    protected void addValidationMessage(SAXParseException exception, int severity)
    {
      if(exception.getSystemId() != null)
      {       	
    	int lineNumber = exception.getLineNumber();
    	int columnNumber = exception.getColumnNumber();
    	
    	// For the following three errors the line number will be modified to use that of the start
    	// tag instead of the end tag.
    	String currentErrorKey = valinfo.currentErrorKey;
    	if (currentErrorKey != null && adjustLocationErrorKeySet.contains(currentErrorKey))  
    	{
    	  LocationCoordinate adjustedCoordinates = (LocationCoordinate)valinfo.getStartElementLocations().peek();
    	  lineNumber = adjustedCoordinates.getLineNumber();
    	  columnNumber = adjustedCoordinates.getColumnNumner();
    	}
    	
        if(severity == WARNING)
        {
          valinfo.addWarning(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId());
        }
        else
        {
          valinfo.addError(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId(), valinfo.getCurrentErrorKey(), valinfo.getMessageArguments());
        }
      }
    }

    /* (non-Javadoc)
     * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
     */
    public void error(SAXParseException exception) throws SAXException
    {
      addValidationMessage(exception, ERROR);
    }

    /* (non-Javadoc)
     * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
     */
    public void fatalError(SAXParseException exception) throws SAXException
    {
      addValidationMessage(exception, ERROR);
    }

    /* (non-Javadoc)
     * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
     */
    public void warning(SAXParseException exception) throws SAXException
    {
      addValidationMessage(exception, WARNING);
    }
  }
                                                                          
  /** 
   * This class is used to count the elementDecls that are encountered in a DTD.
   */
  protected class MyDeclHandler implements DeclHandler 
  {
    
    /**
     * Constructor.
     * 
     * @param valinfo The XMLValidationInfo object that will count the declarations.
     */
    public MyDeclHandler()
    {
    }
    
    /* (non-Javadoc)
     * @see org.xml.sax.ext.DeclHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
     */
    public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) 
    {
    }                                    

    /* (non-Javadoc)
     * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
     */
    public void elementDecl(String name, String model) 
    {
      //valinfo.increaseElementDeclarationCount();
    }
  
    /* (non-Javadoc)
     * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
     */
    public void externalEntityDecl(String name, String publicId, String systemId) 
    {
    }      

    /* (non-Javadoc)
     * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(java.lang.String, java.lang.String)
     */
    public void internalEntityDecl(String name, String value) 
    {
    }
  }

  /**
   * A XIncludeAwareParserConfiguration that creates an error reporter which can ignore
   * DTD error messages for DTD's with no elements defined.
   */

  protected class MyStandardParserConfiguration extends XIncludeAwareParserConfiguration
  {
  	XMLValidationInfo valinfo = null;
    List reportedExceptions = new ArrayList(); 
  	
  	/**
  	 * Constructor.
  	 * 
  	 * @param valinfo The XMLValidationInfo object to use.
  	 */
  	public MyStandardParserConfiguration(XMLValidationInfo valinfo)
  	{
  	  this.valinfo = valinfo;
  	  
  	  XMLErrorReporter errorReporter = createErrorReporter();
      if (errorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
          XMLMessageFormatter xmft = new XMLMessageFormatter();
          errorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
          errorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
      }  	  
      fErrorReporter = errorReporter;
	  setProperty(ERROR_REPORTER, errorReporter);
	  fCommonComponents.remove(fErrorReporter);
	  fCommonComponents.add(fErrorReporter);
  	}

    /* (non-Javadoc)
     * @see org.apache.xerces.parsers.DTDConfiguration#createErrorReporter()
     */
    protected XMLErrorReporter createErrorReporter() 
    {
    	return new XMLErrorReporter()
		{
    		/* (non-Javadoc)
    		 * @see org.apache.xerces.impl.XMLErrorReporter#reportError(java.lang.String, java.lang.String, java.lang.Object[], short)
    		 */
    		public void reportError(String domain, String key, Object[] arguments, short severity) throws XNIException 
    	    {                    
		      boolean reportError = true;
              valinfo.setCurrentErrorKey(key);  
			  valinfo.setMessageArguments(arguments);
		      String ignoreCondition = (String)ingoredErrorKeyTable.get(key);
		      if (ignoreCondition != null)
		      {
		        if (ignoreCondition.equals(XMLValidator.IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL))
		        {                    
		          boolean isDTDWithoutElementDeclarationEncountered = valinfo.isDTDWithoutElementDeclarationEncountered(); 
		          reportError = !isDTDWithoutElementDeclarationEncountered;  
		        }
		        else 
		        {
		          reportError = false;
		        }
		      }
		      if ("schema_reference.4".equals(key) && arguments.length > 0) //$NON-NLS-1$
              {
                Object location = arguments[0];  
                if (location != null)
                {  
                  if(reportedExceptions.contains(location))
                  {
                    reportError = false;
                  }
                  else
                  {
                    reportedExceptions.add(location);
                  }
                }
              }          
		      if (reportError)
		      {
		        super.reportError(domain, key, arguments, severity);
		        valinfo.getErrorCustomizationManager().considerReportedError(valinfo, key, arguments);
		      }
		    }
		};
    }
  }
  
  /** 
   * A line and column number coordinate.
   */
  protected class LocationCoordinate
  {	
	private int lineNo = -1;
    private int columnNo = -1;
    
    public LocationCoordinate(int lineNumber, int columnNumber)
    {
      this.lineNo = lineNumber;
      this.columnNo = columnNumber;
    }
    	
    public int getLineNumber()
    { 
      return this.lineNo;
    }
    	
    public int getColumnNumner()
    { 
      return this.columnNo;
    } 
  }
  
  protected IResource getWorkspaceFileFromLocation(String location)
  {
    if (location == null) return null;
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    // To canonicalize the EMF URI
    IPath canonicalForm = new Path(location);
    // Need to convert to absolute location...
    IPath pathLocation = new Path(URIHelper.removeProtocol(canonicalForm.toString()));
    // ...to find the resource file that is in the workspace
    IResource resourceFile = workspace.getRoot().getFileForLocation(pathLocation);
    // If the resource is resolved to a file from http, or a file outside
    // the workspace, then we will just ignore it.
    return resourceFile;
  }
}
