package org.mandarax.util.resultsetfilters;

/*
 * Copyright (C) 1999-2004 <a href="mailto:mandarax@jbdietrich.com">Jens Dietrich</a>
 *
 * This library 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 library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.util.*;
import org.mandarax.kernel.*;
import org.mandarax.util.*;

/**
 * Filter for result sets. Results having the same substitutions for 
 * a list of query variables (not necessary all of them) but different proofs are identified.
 * Similar to SQLs GROUP BY functionality.
 * A Group By filter is created using a result set and an array of aggregation funtions. 
 * This array can contain null slots, indicating that the respective variable is used
 * in the group by list. The array defines aggregation functions accourding to the 
 * order of the variables in the original result set.
 * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
 * @version 3.3.1 <9 August 2004>
 * @since 3.0
 */

public class OrderByFilter extends CachedResultSet {

	private ResultSet original = null;
	private OrderByCondition[] orderByConditions = null;
	
	// comparator to compare results
	class ResultComparator implements Comparator {
		/**
		 * Compare objects.
		 * @see java.util.Comparator
		 */
		public int compare(Object obj1,Object obj2) {
			int result = 0;
			int counter = 0;
			Object value1 = null;
			Object value2 = null;
			VariableTerm var = null;
			while (result==0 && counter<orderByConditions.length) {
				try {
					var = orderByConditions[counter].getVariable();
					value1 = ((Result)obj1).getResult(var);
					value2 = ((Result)obj2).getResult(var);
					result = orderByConditions[counter].compareTo(value1,value2);
				}
				catch (OrderByException x) {
					result = 0;
					// @todo log
				}
				counter++;
			}
			return result;
		}
	};
	

	/**
	 * Constructor.
	 * @param original a not yet initialized result set (the cursor has not yet been moved)
	 * @param orderByConditions an array of order by conditions
	 */
	public OrderByFilter(ResultSet org,	OrderByCondition[] orderByConditions) throws InferenceException {
		super();
		this.original = org;
		this.orderByConditions = orderByConditions;

		// sort results
		results = new ArrayList();
		// build results
		TreeSet sortedResults = new TreeSet(new ResultComparator());
		while(original.next()) {
			results.add(new ResultImpl(original));
		}

		// sort results	 
		this.results.addAll(sortedResults);
		Collections.sort(results,new ResultComparator());
	}
	/**
	 * Get a list of all variable terms in the query.
	 * @return a list of variable terms
	 */
	public List getQueryVariables() throws InferenceException {
		return original.getQueryVariables();
	}

}
