package eu.dnetlib.dlms.jdbc.server;

import java.sql.SQLException;

import eu.dnetlib.dlms.jdbc.ExecutorContext;
import eu.dnetlib.dlms.jdbc.ast.BinaryPredicate;
import eu.dnetlib.dlms.jdbc.ast.SimplePredicate;
import eu.dnetlib.dlms.jdbc.ast.XPath;
import eu.dnetlib.dlms.jdbc.ast.XPathComponent;
import eu.dnetlib.dlms.jdbc.ast.XPathExpr;

/**
 * Interface to execute ASTNode that composes XPath.
 * 
 * @author alessia
 * 
 */
public interface IXPathExecutor {
	/**
	 * Enumeration for axis elements in an XPathComponent.
	 */
	public enum Axis {
		/**
		 * The as axis is the opposite of deref: it gets the wrappers of the original objects.
		 * <p>
		 * E.g. <code>A/as::C</code> selects the objects in Set C that are wrappers for objects of Set A. In other words
		 * it selects the objects in C that are the result of a cast from the set A to the Set C.
		 * </p>
		 */
		as,
		/**
		 * The attribute axis is to select values of structure objects' fields.
		 */
		attribute,
		/**
		 * The deref axis is the opposite of as: it gets the objects referenced by wrappers.
		 * <p>
		 * E.g. <code>A/deref::C</code> selects the objects in Set C that are referenced by wrappers that are in Set A.
		 * In other words it selects the objects in C that have been casted from C into A.
		 * </p>
		 */
		deref,
		/**
		 * The lift axis is the opposite of tag: it changes the point of view of a query from a Set to the UnionSet
		 * specified by the axis target. To be correct, the Set must be included by the specified UnionSet.
		 * <p>
		 * E.g. <code>S/lift::U</code> changes the concrete type of objects in S to the UnionSet U. Current objects are
		 * to be treated as U objects, not S.
		 * </p>
		 * 
		 */
		lift,
		/**
		 * The relation axis is to stop navigation at the relation object, instead of continuing to the target object.
		 * <p>
		 * E.g. <code>A/B</code> selects the targets of relations labeled B having objects in A as sources.
		 * <code>A/relation::B</code> selects the relations labeled B having objects in A as sources.
		 */
		relation,
		/**
		 * The reverse axis is to navigate backward, from targets to sources.
		 */
		reverse,
		/**
		 * The tag axis is the opposite of lift: it changes the point of view of a query from a UnionSet to the included
		 * set specified by the axis target.
		 * <p>
		 * E.g. <code>U/tag::S</code> selects from the union set U the objects that comes from Set S. Selected objects
		 * are to be considered of concrete type S, not U.
		 * </p>
		 * 
		 */
		tag,
		/**
		 * none axis is not to be used in queries. It is used only internally to help the handling of * when it is at
		 * the beginning of an xPath.
		 */
		none;

	}

	/**
	 * Executes the XPath in the given context.
	 * 
	 * @param xPath
	 *            XPath to execute
	 * @param context
	 *            ExecutorContext representing the current context
	 * @return the new context generated by the XPath execution
	 * @throws SQLException
	 *             problems in execution
	 */
	ExecutorContext execute(XPath xPath, ExecutorContext context) throws SQLException;

	/**
	 * Executes the XPathComponent in the given context.
	 * 
	 * @param xComp
	 *            XPathComponent to execute
	 * @param context
	 *            ExecutorContext representing the current context
	 * @return the new context generated by the XPathComponent execution
	 * @throws SQLException
	 *             problems in execution
	 */
	ExecutorContext execute(XPathComponent xComp, ExecutorContext context) throws SQLException;

	/**
	 * Executes the XPathExpr in the given context.
	 * 
	 * @param xExpr
	 *            XPathExpr to execute
	 * @param context
	 *            ExecutorContext representing the current context
	 * @return the new context generated by the XPathExpr execution
	 * @throws SQLException
	 *             problems in execution
	 */
	ExecutorContext execute(XPathExpr xExpr, ExecutorContext context) throws SQLException;

	/**
	 * Executes the BinaryPredicate in the given context.
	 * 
	 * @param binaryPredicate
	 *            BinaryPredicate to execute
	 * @param context
	 *            ExecutorContext representing the current context
	 * @return the new context generated by the BinaryPredicate execution
	 * @throws SQLException
	 *             problems in execution
	 */
	ExecutorContext execute(BinaryPredicate binaryPredicate, ExecutorContext context) throws SQLException;

	/**
	 * Executes the SimplePredicate in the given context.
	 * 
	 * @param simplePredicate
	 *            SimplePredicate to execute
	 * @param context
	 *            ExecutorContext representing the current context
	 * @return the new context generated by the BinaryPredicate execution
	 * @throws SQLException
	 *             problems in execution
	 */
	ExecutorContext execute(SimplePredicate simplePredicate, ExecutorContext context) throws SQLException;

}
