package org.mandarax.util;

/*
 * 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.ArrayList;
import java.util.HashSet;
import org.mandarax.kernel.Derivation;
import org.mandarax.kernel.InferenceException;
import org.mandarax.kernel.LogicFactory;
import org.mandarax.kernel.Replacement;
import org.mandarax.kernel.Result;
import org.mandarax.kernel.ResultSet;
import org.mandarax.kernel.VariableTerm;

/**
 * Filter for result sets. Results having the same substitutions
 * but different proofs are identified.
 * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
 * @version 3.3.1 <9 August 2004>
 * @since 1.8.1
 */

public class ResultSetFilter extends CachedResultSet {
  private ResultSet original = null;
  private HashSet controllSet = new HashSet();
  private static final LogicFactory lfactory = LogicFactory.getDefaultFactory();
  // private data structures to represent results
  private class ResultImpl extends Result {
    ResultImpl(Derivation d,Replacement[] r) {
      super(d,r);
    }
    public boolean equals(Object o) {
      if (o!=null && o instanceof ResultImpl) {
        ResultImpl r = (ResultImpl)o;
        Replacement[] replacements = getReplacements();
        if (replacements==null) return r.getReplacements()==null;

        for (int i=0;i<replacements.length;i++) {
          if (!replacements[i].equals(r.getReplacements()[i]))  return false;
        }

        return true;
      }
      else return false;
    }
    public int hashCode() {
      int hc = 0;
      Replacement[] replacements = getReplacements();
      if (replacements==null) return hc;
      for (int i=0;i<replacements.length;i++) hc=hc^replacements[i].hashCode();
      return hc;
    }
  }
  /**
   * Constructor.
   * @param original a not yet initialized result set (the cursor has not yet been moved)
   */
  public ResultSetFilter(ResultSet org) throws InferenceException {
    super();
    this.original = org;
    // initialize var list
    vars = org.getQueryVariables();
    // initialize result list
    results = new ArrayList();
    while (original.next()) {
      Result nextResult = getNextResult();
      if (!controllSet.contains(nextResult)) {
        results.add(nextResult);
        controllSet.add(nextResult);
        // System.out.println("Adding result " + nextResult);
      }
    }
  }

  /**
   * Gets the next result from the original result set.
   * @return the next result
   */
   private Result getNextResult() throws InferenceException {
      Replacement[] replacements = new Replacement[vars.size()];
      for (int i=0;i < vars.size();i++) {
        VariableTerm nextVar = (VariableTerm)vars.get(i);
        Object nextReplacement = original.getResult(nextVar);
        replacements[i] = new Replacement(nextVar,lfactory.createConstantTerm(nextReplacement));
      }
      Derivation proof = original.getProof();
      ResultImpl result = new ResultImpl(proof,replacements);
      return result;
   }
}
