/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-06 Wolfgang M. Meier
 *  wolfgang@exist-db.org
 *  http://exist.sourceforge.net
 *  
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *  
 *  $Id: NodeSet.java 4427 2006-09-28 13:33:50Z dizzzz $
 */
package org.exist.dom;

import org.exist.xquery.Expression;
import org.exist.xquery.XPathException;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.Type;
import org.exist.numbering.NodeId;
import org.w3c.dom.NodeList;

/**
 * @author wolf
 */
public interface NodeSet extends Sequence, NodeList {
	
	public final static int ANCESTOR = 0;

	public final static int DESCENDANT = 1;

	public final static int PRECEDING = 2;

	public final static int FOLLOWING = 3;

	/**
	 * Constant representing an empty node set.
	 */
	public final static NodeSet EMPTY_SET = new EmptyNodeSet();
		
	/**
	 * Return an iterator on the nodes in this list. The iterator returns nodes
	 * according to the internal ordering of nodes (i.e. level first), not in document-
	 * order.
	 * 
	 */
	public NodeSetIterator iterator();
	
	/**
	 * Check if this node set contains a node matching the document and
	 * node-id of the given NodeProxy object.
	 * 
	 * @param proxy
	 */
	public boolean contains(NodeProxy proxy);
	
	/**
	 * Check if this node set contains nodes belonging to the given document.
	 * 
	 * @param doc
	 */
	public boolean containsDoc(DocumentImpl doc);
	
	public DocumentSet getDocumentSet();
	
	/**
	 * Add a new proxy object to the node set. Please note: node set
	 * implementations may allow duplicates.
	 * 
	 * @param proxy
	 */
	public void add(NodeProxy proxy);
	
	/**
	 * Add a proxy object to the node set. The sizeHint parameter
	 * gives a hint about the number of items to be expected for the
	 * current document.
	 * 
	 * @param proxy
	 * @param sizeHint
	 */
	public void add(NodeProxy proxy, int sizeHint);
	
	/**
	 * Add all nodes from the given node set.
	 * 
	 * @param other
	 */
	public void addAll(NodeSet other);	

	/**
	 * Get the node at position pos within this node set.
	 * @param pos
	 */
	public NodeProxy get(int pos);
	
	/**
	 * Get a node from this node set matching the document and node id of
	 * the given NodeProxy.
	 *  
	 * @param p
	 */
	public NodeProxy get(NodeProxy p);
	
    public NodeProxy get(DocumentImpl doc, NodeId nodeId);

    /**
	 * Check if any child nodes are found within this node set for a given
	 * set of potential parent nodes.
	 * 
	 * If mode is {@link #DESCENDANT}, the returned node set will contain
	 * all child nodes found in this node set for each parent node. If mode is
	 * {@link #ANCESTOR}, the returned set will contain those parent nodes,
	 * for which children have been found.
	 *  
	 * @param al a node set containing potential parent nodes
	 * @param mode selection mode
	 */
	public NodeSet selectParentChild(NodeSet al, int mode);
	
	/**
	 * Check if any child nodes are found within this node set for a given
	 * set of potential parent nodes.
	 * 
	 * If mode is {@link #DESCENDANT}, the returned node set will contain
	 * all child nodes found in this node set for each parent node. If mode is
	 * {@link #ANCESTOR}, the returned set will contain those parent nodes,
	 * for which children have been found.
	 *  
	 * @param al a node set containing potential parent nodes
	 * @param mode selection mode
	 * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection. 
	 */
	
	public NodeSet selectParentChild(NodeSet al, int mode, int contextId);
		
	/**
	 * Check if any descendant nodes are found within this node set for a given
	 * set of potential ancestor nodes.
	 * 
	 * If mode is {@link #DESCENDANT}, the returned node set will contain
	 * all descendant nodes found in this node set for each ancestor. If mode is
	 * {@link #ANCESTOR}, the returned set will contain those ancestor nodes,
	 * for which descendants have been found.
	 *  
	 * @param al a node set containing potential parent nodes
	 * @param mode selection mode
	 * @param includeSelf if true, check if the ancestor node itself is contained in
	 * the set of descendant nodes (descendant-or-self axis)
	 * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection. 
	 */
	public NodeSet selectAncestorDescendant(NodeSet al,	int mode, boolean includeSelf, int contextId);
		
	/**
	 * For a given set of potential ancestor nodes, return all ancestors
	 * having descendants in this node set.
	 *
	 * @param  descendants    node set containing potential ancestors
	 * @param includeSelf if true, check if the ancestor node itself is contained
	 * in this node set (ancestor-or-self axis)
	 * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection. 
	 */
	public NodeSet selectAncestors(NodeSet descendants, boolean includeSelf,	int contextId);

    /**
     * Select all nodes from the passed node set, which
     * are preceding siblings of the nodes in
     * this set.
     * 
     * @param siblings a node set containing potential siblings
     * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection.  
     */
    public NodeSet selectPrecedingSiblings(NodeSet siblings, int contextId);

    /**
     * Select all nodes from the passed node set, which
     * are following siblings of the nodes in
     * this set.
     * 
     * @param siblings a node set containing potential siblings
     * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection.     
     */    
    public NodeSet selectFollowingSiblings(NodeSet siblings, int contextId);
	
    public NodeSet selectPreceding(NodeSet preceding) throws XPathException;
    
    public NodeSet selectFollowing(NodeSet following) throws XPathException;
    
	/**
	 * Check if the node identified by its node id has an ancestor contained in this node set
	 * and return the ancestor found.
	 *
	 * If directParent is true, only immediate ancestors (parents) are considered.
	 * Otherwise the method will call itself recursively for all the node's
	 * parents.
	 *
	 * If includeSelf is true, the method returns also true if
	 * the node itself is contained in the node set.
	 */
    public NodeProxy parentWithChild(DocumentImpl doc, NodeId nodeId, boolean directParent, boolean includeSelf);

    /**
	 * Check if the given node has an ancestor contained in this node set
	 * and return the ancestor found.
	 *
	 * If directParent is true, only immediate ancestors (parents) are considered.
	 * Otherwise the method will call itself recursively for all the node's
	 * parents.
	 *
	 * If includeSelf is true, the method returns also true if
	 * the node itself is contained in the node set.
	 */
	public NodeProxy parentWithChild(NodeProxy proxy, boolean directParent,	boolean includeSelf, int level);

    /**
	 * Return a new node set containing the parent nodes of all nodes in the 
	 * current set.
	 */
	public NodeSet getParents(int contextId);
	
    public NodeSet getAncestors(int contextId, boolean includeSelf);
    
    /**
     * Optimized method to select attributes. Use this if the context has just one or
     * two nodes. Attributes will be directly looked up in the persistent DOM store.
     *  
     * @param qname the QName of the attribute
     * @param contextId used to track context nodes when evaluating predicate 
     * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
     * will be added to each result of the of the selection. 
     */
    public NodeSet directSelectAttribute(QName qname, int contextId);
    
	/**
	 * If all nodes in this set have an index, returns the common
	 * supertype used to build the index, e.g. xs:integer or xs:string.
	 * If the nodes have different index types or no node has been indexed,
	 * returns {@link Type#ITEM}.
	 * 
	 * @see org.exist.xquery.GeneralComparison
	 * @see org.exist.xquery.ValueComparison
	 */
	public int getIndexType();
	
	public boolean hasTextIndex();
	
	public boolean hasMixedContent();
	
	/**
	 * Get a hint about how many nodes in this node set belong to the 
	 * specified document. This is just used for allocating new node sets.
	 * The information does not need to be exact. -1 is returned if the
	 * size cannot be determined (the default).
	 * 
	 * @param doc
	 */
	public int getSizeHint(DocumentImpl doc);
	
	/**
	 * Return a new node set, which represents the intersection of the current
	 * node set with the given node set.
	 * 
	 * @param other
	 */
	public NodeSet intersection(NodeSet other);
	
	/**
	 * Return a new node set, containing all nodes in this node set that
	 * are contained or have descendants in the other node set.
	 * 
	 * @param other
	 */
	public NodeSet deepIntersection(NodeSet other);
	
	/**
	 * Return a new node set which represents the union of the
	 * current node set and the given node set.
	 * 
	 * @param other
	 */
	public NodeSet union(NodeSet other);
	
	/**
	 * Return a new node set containing all nodes from this node set
	 * except those nodes which are also contained in the argument node set.
	 * 
	 * @param other
	 */
	public NodeSet except(NodeSet other);
	
    public void setProcessInReverseOrder(boolean inReverseOrder);

    public boolean getProcessInReverseOrder();
	
	/**
	 * Returns all context nodes associated with the nodes in
	 * this node set.
	 *  
	 * @param contextId used to track context nodes when evaluating predicate 
	 * expressions. If contextId != {@link Expression#NO_CONTEXT_ID}, the current context
	 * will be added to each result of the of the selection. 
	 */
	public NodeSet getContextNodes(int contextId);
	
	public boolean hasChanged(int previousState);
	
	public int getState();
}
