/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */


package org.apache.xpath.domapi;

import javax.xml.transform.TransformerException;

import org.apache.xalan.res.XSLMessages;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.res.XPATHErrorResources;

import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.traversal.NodeIterator;
import org.w3c.dom.xpath.XPathException;
import org.w3c.dom.xpath.XPathResult;

/**
 *
 * The class provides an implementation XPathResult according 
 * to the DOM L3 XPath Specification, Working Draft 28, March 2002.
 *
 * <p>See also the <a href='http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020328'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
 * 
 * <p>The <code>XPathResult</code> interface represents the result of the 
 * evaluation of an XPath expression within the context of a particular 
 * node. Since evaluation of an XPath expression can result in various 
 * result types, this object makes it possible to discover and manipulate 
 * the type and value of the result.</p>
 * 
 * <p>This implementation wraps an <code>XObject</code>.
 * 
 * @see org.apache.xpath.objects.XObject
 * @see org.w3c.dom.xpath.XPathResult
 * 
 * @xsl.usage experimental
 */
public class XPathResultImpl implements XPathResult, EventListener {

	/**
     *  The wrapped XObject
     */
	private XObject m_resultObj;
	
	/**
     *  This the type specified by the user during construction.  Typically
	 *  the constructor will be called by org.apache.xpath.XPath.evaluate().
     */
	private short m_resultType = ANY_TYPE; 
	
	private boolean m_isInvalidIteratorState = false;
	
    /**
     * Only used to attach a mutation event handler when specified
     * type is an iterator type.
     */
	private Node m_contextNode;
	
	/**
     *  The iterator, if this is an iterator type.
     */
	private NodeIterator m_iterator = null;
	
	/**
     *  The list, if this is a snapshot type.
     */
	private NodeList m_list = null;
	

	/**
	 * Constructor for XPathResultImpl.
     * 
     * For internal use only.
	 */
	 XPathResultImpl(short type, XObject result, Node contextNode) {
		// Check that the type is valid
		if (!isValidType(type)) {
            String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});       
            throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}           
		}

        // Result object should never be null!
        if (null == result) {
            String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_EMPTY_XPATH_RESULT, null);       
            throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,fmsg); // Empty XPath result object
        }
        
        this.m_resultObj = result;
        this.m_contextNode = contextNode;

        // If specified result was ANY_TYPE, determine XObject type
        if (type == ANY_TYPE) {
            this.m_resultType = getTypeFromXObject(result);
        } else {
            this.m_resultType = type;
        }
		
        // If the context node supports DOM Events and the type is one of the iterator
        // types register this result as an event listener
        if (((m_resultType == XPathResult.ORDERED_NODE_ITERATOR_TYPE) ||
            (m_resultType == XPathResult.UNORDERED_NODE_ITERATOR_TYPE))&&
            (contextNode instanceof EventTarget)) {
                ((EventTarget)contextNode).addEventListener("MutationEvents",this,true);
        }// else can we handle iterator types if contextNode doesn't support EventTarget??
    				
        // If this is an iterator type get the iterator
        if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) ||
            (m_resultType == UNORDERED_NODE_ITERATOR_TYPE) ||
            (m_resultType == ANY_UNORDERED_NODE_TYPE) ||
            (m_resultType == FIRST_ORDERED_NODE_TYPE))  {
    
            try {
                m_iterator = m_resultObj.nodeset();
            } catch (TransformerException te) {
                // probably not a node type
                String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});       
                throw new XPathException(XPathException.TYPE_ERR, fmsg);  // The returned type: {0} can not be coerced into the specified type: {1}
            }
    
                // If user requested ordered nodeset and result is unordered 
                // need to sort...TODO
    //            if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) &&
    //                (!(((DTMNodeIterator)m_iterator).getDTMIterator().isDocOrdered()))) {
    // 
    //            }
    
        // If it's a snapshot type, get the nodelist
        } else if ((m_resultType == UNORDERED_NODE_SNAPSHOT_TYPE) ||
                   (m_resultType == ORDERED_NODE_SNAPSHOT_TYPE)) {
            try {       	
        	   m_list = m_resultObj.nodelist();
            } catch (TransformerException te) {
        		// probably not a node type 
                String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});       
                throw new XPathException(XPathException.TYPE_ERR, fmsg);  // The returned type: {0} can not be coerced into the specified type: {1}
            }
    	}	    	 
	}

	/**
	 * @see org.w3c.dom.xpath.XPathResult#getResultType()
	 */
	public short getResultType() {
		return m_resultType;
	}

	/**
	 *  The value of this number result.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>NUMBER_TYPE</code>.
	 * @see org.w3c.dom.xpath.XPathResult#getNumberValue()
	 */
	public double getNumberValue() throws XPathException {
		if (getResultType() != NUMBER_TYPE) {
			String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_NUMBER, new Object[] {getTypeString(m_resultType)});		
			throw new XPathException(XPathException.TYPE_ERR,fmsg); // Can not convert {0} to a number
		} else {
			try {
			   return m_resultObj.num();
			} catch (Exception e) {
				// Type check above should prevent this exception from occurring.
				throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
			}
		}		
	}

	/**
	 * The value of this string result.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>STRING_TYPE</code>.
     * 
	 * @see org.w3c.dom.xpath.XPathResult#getStringValue()
	 */
	public String getStringValue() throws XPathException {
		if (getResultType() != STRING_TYPE) {
			String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_STRING, new Object[] {m_resultObj.getTypeString()});		
			throw new XPathException(XPathException.TYPE_ERR,fmsg); // Can not convert {0} to a string.
		} else {
			try {
			   return m_resultObj.str();
			} catch (Exception e) {
				// Type check above should prevent this exception from occurring.
				throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
			}
		}
	}

	/**
	 * @see org.w3c.dom.xpath.XPathResult#getBooleanValue()
	 */
	public boolean getBooleanValue() throws XPathException {
		if (getResultType() != BOOLEAN_TYPE) {
			String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_BOOLEAN, new Object[] {getTypeString(m_resultType)});		
			throw new XPathException(XPathException.TYPE_ERR,fmsg);  // Can not convert {0} to a boolean
		} else {
			try {
			   return m_resultObj.bool();
			} catch (TransformerException e) {
				// Type check above should prevent this exception from occurring.
				throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
			}
		}
	}

	/**
	 * The value of this single node result, which may be <code>null</code>.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>ANY_UNORDERED_NODE_TYPE</code> or 
     *   <code>FIRST_ORDERED_NODE_TYPE</code>.
     * 
	 * @see org.w3c.dom.xpath.XPathResult#getSingleNodeValue()
	 */
	public Node getSingleNodeValue() throws XPathException {
		
		if ((m_resultType != ANY_UNORDERED_NODE_TYPE) &&
		    (m_resultType != FIRST_ORDERED_NODE_TYPE)) {
           String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_SINGLENODE, new Object[] {getTypeString(m_resultType)});                        
		   throw new XPathException(XPathException.TYPE_ERR,fmsg); // Can not convert {0} to a single node. This getter applies to types 
                                                                 // ANY_UNORDERED_NODE_TYPE and FIRST_ORDERED_NODE_TYPE.
	    }
	
		NodeIterator result = null;
		try {
			result = m_resultObj.nodeset();
		} catch (TransformerException te) {
			throw new XPathException(XPathException.TYPE_ERR,te.getMessage());
		}
        
        if (null == result) return null;
        
        Node node = result.nextNode();
         
        // Wrap "namespace node" in an XPathNamespace 
        if (isNamespaceNode(node)) {
            return new XPathNamespaceImpl(node);
        } else {
            return node;
        }        
	}

	/**
	 * @see org.w3c.dom.xpath.XPathResult#getInvalidIteratorState()
	 */
	public boolean getInvalidIteratorState() {
		return m_isInvalidIteratorState;
	}

	/**
	 * The number of nodes in the result snapshot. Valid values for 
     * snapshotItem indices are <code>0</code> to 
     * <code>snapshotLength-1</code> inclusive.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>UNORDERED_NODE_SNAPSHOT_TYPE</code> or 
     *   <code>ORDERED_NODE_SNAPSHOT_TYPE</code>.
     * 
	 * @see org.w3c.dom.xpath.XPathResult#getSnapshotLength()
	 */
	public int getSnapshotLength() throws XPathException {
	
		if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
		    (m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
           String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_GET_SNAPSHOT_LENGTH, new Object[] {getTypeString(m_resultType)});                        
		   throw new XPathException(XPathException.TYPE_ERR,fmsg); // Can not get snapshot length on type: {0}. This getter applies to types 
                                                         //UNORDERED_NODE_SNAPSHOT_TYPE and ORDERED_NODE_SNAPSHOT_TYPE.
	    }
			
		return m_list.getLength();
	}

	/**
	 * Iterates and returns the next node from the node set or 
     * <code>null</code>if there are no more nodes.
     * @return Returns the next node.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>UNORDERED_NODE_ITERATOR_TYPE</code> or 
     *   <code>ORDERED_NODE_ITERATOR_TYPE</code>.
     * @exception DOMException
     *   INVALID_STATE_ERR: The document has been mutated since the result was 
     *   returned.
	 * @see org.w3c.dom.xpath.XPathResult#iterateNext()
	 */
	public Node iterateNext() throws XPathException, DOMException {
		if ((m_resultType != UNORDERED_NODE_ITERATOR_TYPE) &&
		    (m_resultType != ORDERED_NODE_ITERATOR_TYPE)) {
          String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NON_ITERATOR_TYPE, new Object[] {getTypeString(m_resultType)});                        
		  throw new XPathException(XPathException.TYPE_ERR, fmsg);  // Can not iterate over non iterator type: {0}
	    }

		if (getInvalidIteratorState()) {
          String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_DOC_MUTATED, null);                        
		  throw new DOMException(DOMException.INVALID_STATE_ERR,fmsg);  // Document mutated since result was returned. Iterator is invalid.
		}			 

        Node node = m_iterator.nextNode();
        
        // Wrap "namespace node" in an XPathNamespace 
        if (isNamespaceNode(node)) {
            return new XPathNamespaceImpl(node);
        } else {
            return node;
        }
	}

    /**
     * Returns the <code>index</code>th item in the snapshot collection. If 
     * <code>index</code> is greater than or equal to the number of nodes in 
     * the list, this method returns <code>null</code>. Unlike the iterator 
     * result, the snapshot does not become invalid, but may not correspond 
     * to the current document if it is mutated.
     * @param index Index into the snapshot collection.
     * @return The node at the <code>index</code>th position in the 
     *   <code>NodeList</code>, or <code>null</code> if that is not a valid 
     *   index.
     * @exception XPathException
     *   TYPE_ERR: raised if <code>resultType</code> is not 
     *   <code>UNORDERED_NODE_SNAPSHOT_TYPE</code> or 
     *   <code>ORDERED_NODE_SNAPSHOT_TYPE</code>.
     *
	 * @see org.w3c.dom.xpath.XPathResult#snapshotItem(int)
	 */
	public Node snapshotItem(int index) throws XPathException {
		
		if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
		    (m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
           String fmsg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NON_SNAPSHOT_TYPE, new Object[] {getTypeString(m_resultType)});                        
           throw new XPathException(XPathException.TYPE_ERR, fmsg); // Can call snapshotItem on type: {0}. This method applies to types 
                                                              // UNORDERED_NODE_SNAPSHOT_TYPE and ORDERED_NODE_SNAPSHOT_TYPE.
	    }		
        
        Node node = m_list.item(index);
        
        // Wrap "namespace node" in an XPathNamespace 
        if (isNamespaceNode(node)) {
            return new XPathNamespaceImpl(node);
        } else {
            return node;
        }
	}

	
	/**
	 * Check if the specified type is one of the supported types.
	 * @param type The specified type
	 * 
	 * @return true If the specified type is supported; otherwise, returns false.
	 */
	public static boolean isValidType( short type ) {
		switch (type) {
			case ANY_TYPE:
			case NUMBER_TYPE:
			case STRING_TYPE:
			case BOOLEAN_TYPE:
			case UNORDERED_NODE_ITERATOR_TYPE:
			case ORDERED_NODE_ITERATOR_TYPE:
			case UNORDERED_NODE_SNAPSHOT_TYPE:
			case ORDERED_NODE_SNAPSHOT_TYPE:
			case ANY_UNORDERED_NODE_TYPE:
			case FIRST_ORDERED_NODE_TYPE: return true;
			default: return false;
		}
	}

	/**
	 * @see org.w3c.dom.events.EventListener#handleEvent(Event)
	 */
	public void handleEvent(Event event) {
		
		if (event.getType().equals("MutationEvents")) {
			// invalidate the iterator
			m_isInvalidIteratorState = true;
			
			// deregister as a listener to reduce computational load
			((EventTarget)m_contextNode).removeEventListener("MutationEvents",this,true);
			
		}
	}
    
  /**
   * Given a request type, return the equivalent string.
   * For diagnostic purposes.
   *
   * @return type string 
   */
  public String getTypeString(int type)
  {
     switch (type) {
      case ANY_TYPE: return "ANY_TYPE";
      case ANY_UNORDERED_NODE_TYPE: return "ANY_UNORDERED_NODE_TYPE";
      case BOOLEAN_TYPE: return "BOOLEAN";
      case FIRST_ORDERED_NODE_TYPE: return "FIRST_ORDERED_NODE_TYPE";
      case NUMBER_TYPE: return "NUMBER_TYPE";
      case ORDERED_NODE_ITERATOR_TYPE: return "ORDERED_NODE_ITERATOR_TYPE";
      case ORDERED_NODE_SNAPSHOT_TYPE: return "ORDERED_NODE_SNAPSHOT_TYPE";
      case STRING_TYPE: return "STRING_TYPE";
      case UNORDERED_NODE_ITERATOR_TYPE: return "UNORDERED_NODE_ITERATOR_TYPE";
      case UNORDERED_NODE_SNAPSHOT_TYPE: return "UNORDERED_NODE_SNAPSHOT_TYPE";
      default: return "#UNKNOWN";
    }
  }  
  
  /**
   * Given an XObject, determine the corresponding DOM XPath type
   * 
   * @return type string
   */
  private short getTypeFromXObject(XObject object) {
      switch (object.getType()) {
        case XObject.CLASS_BOOLEAN: return BOOLEAN_TYPE;
        case XObject.CLASS_NODESET: return UNORDERED_NODE_ITERATOR_TYPE; 
        case XObject.CLASS_NUMBER: return NUMBER_TYPE;
        case XObject.CLASS_STRING: return STRING_TYPE;
        // XPath 2.0 types                         
//          case XObject.CLASS_DATE: 
//          case XObject.CLASS_DATETIME:
//          case XObject.CLASS_DTDURATION:
//          case XObject.CLASS_GDAY:
//          case XObject.CLASS_GMONTH:
//          case XObject.CLASS_GMONTHDAY:
//          case XObject.CLASS_GYEAR:
//          case XObject.CLASS_GYEARMONTH: 
//          case XObject.CLASS_TIME:
//          case XObject.CLASS_YMDURATION: return STRING_TYPE; // treat all date types as strings?
      
        case XObject.CLASS_RTREEFRAG: return UNORDERED_NODE_ITERATOR_TYPE; 
        case XObject.CLASS_NULL: return ANY_TYPE; // throw exception ?
        default: return ANY_TYPE; // throw exception ?
    }     
    
  }  

/**
 * Given a node, determine if it is a namespace node.
 * 
 * @param node 
 * 
 * @return boolean Returns true if this is a namespace node; otherwise, returns false.
 */
  private boolean isNamespaceNode(Node node) {
    
     if ((null != node) && 
         (node.getNodeType() == Node.ATTRIBUTE_NODE) &&
         (node.getNodeName().startsWith("xmlns:") || node.getNodeName().equals("xmlns"))) {
        return true;   
     } else {
        return false;
     }
  }
  
}
