/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.cache.query.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.geode.InternalGemFireError;
import org.apache.geode.cache.EntryDestroyedException;
import org.apache.geode.cache.query.AmbiguousNameException;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.index.IndexManager;
import org.apache.geode.cache.query.internal.index.IndexProtocol;
import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes;
import org.apache.geode.cache.query.internal.types.StructTypeImpl;
import org.apache.geode.cache.query.types.ObjectType;
import org.apache.geode.internal.Assert;

/**
 * Conjunctions and Disjunctions (LITERAL_and LITERAL_or) As a part of feature development to ensure
 * index usage for multiple regions & index usage in equi join conditions across the regions , a
 * CompiledJunction's organized operands method creates internal structures like GroupJunction,
 * AllGroupJunction & CompositeGroupJunction. The method createJunction is where the decision of
 * creating an AllGroupJunction ( wrapping multiple GroupJunctions and CompositeGroupJunctions) or a
 * single GroupJunction or a singe CompositeGroupJunction is taken.
 *
 * CompiledJunction -----> on organization of Operands may result in any of the following cases
 *
 * 1) CompiledJunction | | -------------------------------- | | CompiledJunction GroupJunction
 * (Filter evaluable) (Filter evaluable)
 *
 * 2) CompiledJunction | | -------------------------------- | | CompiledJunction RangeJunction
 * (Filter evaluable same index operands. May contain iter operands belonging to the same Group)
 * (Filter evaluable)
 *
 *
 * 3) CompiledJunction | | -------------------------------- | | CompiledJunction GroupJunction
 * (Filter evaluable) (Filter evaluable) | | ---------------------------------------------- | |
 * CompiledComparison RangeJunction (at least one filter evaluable compiled Comparison using an
 * index shared by no other condition)
 *
 *
 * 5) CompiledJunction | | -------------------------------- | | CompiledJunction GroupJunction
 * (Filter evaluable) (Filter evaluable) | | --------------------------------------- | | |
 * RangeJunction RangeJunction CompiledComparison (zero or more Filter evaluable or iter evaluable )
 *
 * 6) CompiledJunction | ---------------------------------- | | CompiledJunction AllGroupJunction
 * (filter evaluable) | ------------------------------------------------ | | | GroupJunction
 * GroupJunction CompositeGroupJunction | --------------------------------------- | | |
 * GroupJunction equi join conditions GroupJunction
 *
 *
 *
 * @version $Revision: 1.2 $
 */
public class CompiledJunction extends AbstractCompiledValue implements Negatable {

  /** left operand */
  private final CompiledValue[] _operands;
  private int _operator = 0;
  private List unevaluatedFilterOperands = null;

  // A token to place into the samesort map. This is to let the engine know there is more than one
  // index
  // being used for this junction but allows actual operands to form range junctions if enough
  // exist.
  // The mechanism checks to see if the mapped object is an integer, if so, it increments, if it's
  // not it sets as 1
  // Because we are a string place holder, the next actual operand would just start at one. If the
  // join is added
  // after a valid operand has already set the counter to an integer, we instead just ignore and do
  // not set the place holder
  private static final String PLACEHOLDER_FOR_JOIN = "join";

  CompiledJunction(CompiledValue[] operands, int operator) {
    // invariant: operator must be LITERAL_and or LITERAL_or
    // invariant: at least two operands
    if (!((operator == LITERAL_or || operator == LITERAL_and) && operands.length >= 2)) {
      throw new InternalGemFireError(
          "operator=" + operator + "operands.length =" + operands.length);
    }
    _operator = operator;
    _operands = operands;
  }

  @Override
  public List getChildren() {
    return Arrays.asList(this._operands);
  }

  @Override
  public int getType() {
    return JUNCTION;
  }

  @Override
  public Object evaluate(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    Object r = _operands[0].evaluate(context); // UNDEFINED, null, or a Boolean
    // if it's true, and op is or then return true immediately
    // if it's false and the op is and then return false immediately
    if (r instanceof Boolean)
      if (((Boolean) r).booleanValue() && _operator == LITERAL_or)
        return r;
      else if (!((Boolean) r).booleanValue() && _operator == LITERAL_and)
        return r;
    if (r == null || r == QueryService.UNDEFINED)
      r = QueryService.UNDEFINED; // keep going to see if we hit a
    // short-circuiting truth value
    else if (!(r instanceof Boolean))
      throw new TypeMismatchException(
          String.format(
              "LITERAL_and/LITERAL_or operands must be of type boolean, not type ' %s '",
              r.getClass().getName()));
    for (int i = 1; i < _operands.length; i++) {
      Object ri = null;
      try {
        ri = _operands[i].evaluate(context); // UNDEFINED, null, or
      } catch (EntryDestroyedException ede) {
        continue;
      }
      // Boolean
      if (ri instanceof Boolean)
        if (((Boolean) ri).booleanValue() && _operator == LITERAL_or)
          return ri;
        else if (!((Boolean) ri).booleanValue() && _operator == LITERAL_and)
          return ri;
      if (ri == null || ri == QueryService.UNDEFINED || r == QueryService.UNDEFINED) {
        r = QueryService.UNDEFINED;
        continue; // keep going to see if we hit a short-circuiting truth value
      } else if (!(ri instanceof Boolean))
        throw new TypeMismatchException(
            String.format(
                "LITERAL_and/LITERAL_or operands must be of type boolean, not type ' %s '",
                ri.getClass().getName()));
      // now do the actual and/or
      if (_operator == LITERAL_and)
        r = Boolean.valueOf(((Boolean) r).booleanValue() && ((Boolean) ri).booleanValue());
      else
        // LITERAL_or
        r = Boolean.valueOf(((Boolean) r).booleanValue() || ((Boolean) ri).booleanValue());
    }
    return r;
  }

  @Override
  public Set computeDependencies(ExecutionContext context)
      throws TypeMismatchException, AmbiguousNameException, NameResolutionException {
    for (int i = 0; i < _operands.length; i++) {
      context.addDependencies(this, this._operands[i].computeDependencies(context));
    }
    return context.getDependencySet(this, true);
  }

  @Override
  public SelectResults filterEvaluate(ExecutionContext context, SelectResults intermediateResults)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    OrganizedOperands newOperands = organizeOperands(context);
    SelectResults result = intermediateResults;
    Support.Assert(newOperands.filterOperand != null);
    // evaluate directly on the operand
    result =
        newOperands.isSingleFilter ? (newOperands.filterOperand).filterEvaluate(context, result)
            : (newOperands.filterOperand).auxFilterEvaluate(context, result);
    if (!newOperands.isSingleFilter) {
      List unevaluatedOps =
          ((CompiledJunction) newOperands.filterOperand).unevaluatedFilterOperands;
      if (unevaluatedOps != null) {
        if (newOperands.iterateOperand == null) {
          if (unevaluatedOps.size() == 1) {
            newOperands.iterateOperand = (CompiledValue) unevaluatedOps.get(0);
          } else {
            int len = unevaluatedOps.size();
            CompiledValue[] iterOps = new CompiledValue[len];
            for (int i = 0; i < len; i++) {
              iterOps[i] = (CompiledValue) unevaluatedOps.get(i);
            }
            newOperands.iterateOperand = new CompiledJunction(iterOps, getOperator());
          }
        } else {
          // You cannot have two CompiledJunctions a the same level
          if (newOperands.iterateOperand instanceof CompiledJunction) {
            CompiledJunction temp = (CompiledJunction) newOperands.iterateOperand;
            List prevOps = temp.getOperands();
            unevaluatedOps.addAll(prevOps);
          } else {
            unevaluatedOps.add(newOperands.iterateOperand);
          }
          int totalLen = unevaluatedOps.size();
          CompiledValue[] combinedOps = new CompiledValue[totalLen];
          Iterator itr = unevaluatedOps.iterator();
          int j = 0;
          while (itr.hasNext()) {
            combinedOps[j++] = (CompiledValue) itr.next();
          }
          newOperands.iterateOperand = new CompiledJunction(combinedOps, getOperator());
        }
      }
    }
    if (newOperands.iterateOperand != null)
      // call private method here to evaluate
      result = auxIterateEvaluate(newOperands.iterateOperand, context, result);
    return result;
  }

  private List getCondtionsSortedOnIncreasingEstimatedIndexResultSize(ExecutionContext context)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    // The checks invoked before this function have ensured that all the
    // operands are of type ComparisonQueryInfo and of the form 'var = constant'.
    // Also need for sorting will not arise if there are only two operands
    int len = this._operands.length;
    List sortedList = new ArrayList(len);
    for (int i = 0; i < len; ++i) {
      Filter toSort = (Filter) this._operands[i];
      int indxRsltToSort = toSort.getSizeEstimate(context);
      int sortedListLen = sortedList.size();
      int j = 0;
      for (; j < sortedListLen; ++j) {
        Filter currSorted = (Filter) sortedList.get(j);
        if (currSorted.getSizeEstimate(context) > indxRsltToSort) {
          break;
        }
      }
      sortedList.add(j, toSort);
    }
    return sortedList;
  }

  /**
   * invariant: all operands are known to be evaluated as a filter no operand organization is
   * necessary
   */
  @Override
  public SelectResults auxFilterEvaluate(ExecutionContext context,
      SelectResults intermediateResults) throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    // evaluate the result set from the indexed values
    // using the intermediate results so far (passed in)
    // put results into new intermediate results
    List sortedConditionsList =
        this.getCondtionsSortedOnIncreasingEstimatedIndexResultSize(context);

    // Sort the operands in increasing order of resultset size
    Iterator sortedConditionsItr = sortedConditionsList.iterator();
    while (sortedConditionsItr.hasNext()) {
      // Asif:TODO The intermediate ResultSet should be passed as null when invoking
      // filterEvaluate. Just because filterEvaluate is being called, itself
      // guarantees that there will be at least on auxFilterEvalaute call.
      // The filterEvalaute will return after invoking auxIterEvaluate.
      // The auxIterEvaluate cannot get invoked for an OR junction.
      // The approach of calculation of resultset should be Bubble UP ( i.e
      // bottom to Top of the tree. This implies that for filterEvaluate, we
      // should not be passing IntermediateResultSet.
      // Each invocation of filterEvaluate will be complete in itself with the
      // recursion being ended by evaluating auxIterEvaluate if any. The passing
      // of IntermediateResult in filterEvalaute causes AND junction evaluation
      // to be corrupted , if the intermediateResultset contains some value.
      SelectResults filterResults =
          ((Filter) sortedConditionsItr.next()).filterEvaluate(context, null);
      if (_operator == LITERAL_and) {
        if (filterResults != null && filterResults.isEmpty()) {
          return filterResults;
        } else if (filterResults != null) {
          intermediateResults = (intermediateResults == null) ? filterResults
              : QueryUtils.intersection(intermediateResults, filterResults, context);

          sortedConditionsItr.remove();

          if (intermediateResults.size() <= indexThresholdSize) {
            // Abort further intersection , the remaining filter operands will be
            // transferred for
            // iter evaluation
            break;
          }
        }
      } else {
        // Asif : In case of OR clause, the filterEvaluate cannot return a
        // null value ,as a null value implies Cartesian of Iterators
        // in current scope which can happen only if the operand of OR
        // clause evaluates to true (& which we are not allowing).
        // Though if the operand evaluates to false,it is permissible case
        // for filterEvaluation.
        Assert.assertTrue(filterResults != null);
        intermediateResults = intermediateResults == null ? filterResults
            : QueryUtils.union(intermediateResults, filterResults, context);
      }
    }
    if (_operator == LITERAL_and && !sortedConditionsList.isEmpty()) {
      this.unevaluatedFilterOperands = sortedConditionsList;
    }
    return intermediateResults;
  }

  /** invariant: the operand is known to be evaluated by iteration */
  SelectResults auxIterateEvaluate(CompiledValue operand, ExecutionContext context,
      SelectResults intermediateResults) throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    // Asif: This can be a valid value if we have an AND condition like ID=1 AND
    // true = true. In such cases , if an index is not available on ID still we
    // have at least one expression which is independent of current scope. In
    // such cases a value of null means ignore the null ( because it means all
    // the results ) thus a the result-set of current auxIterate which will be
    // the subset of total result-set , will be the right data.

    // auxIterEvalaute can be called only from an AND junction.

    // This also implies that there will be at least one operand which will be
    // evaluated using auxFilterEvaluate.Thus the result-set given to this
    // function can be empty ( obtained using auxFilterEvaluate ,meaning no need
    // to do iterations below ) but it can never be null. As null itself
    // signifies that the junction cannot be evaluated as a filter.
    if (intermediateResults == null)
      throw new RuntimeException(
          "intermediateResults can not be null");
    if (intermediateResults.isEmpty()) // short circuit
      return intermediateResults;
    List currentIters = context.getCurrentIterators();
    RuntimeIterator rIters[] = new RuntimeIterator[currentIters.size()];
    currentIters.toArray(rIters);
    ObjectType elementType = intermediateResults.getCollectionType().getElementType();
    SelectResults resultSet;
    if (elementType.isStructType()) {
      resultSet = QueryUtils.createStructCollection(context, (StructTypeImpl) elementType);
    } else {
      resultSet = QueryUtils.createResultCollection(context, elementType);
    }


    QueryObserver observer = QueryObserverHolder.getInstance();
    try {
      observer.startIteration(intermediateResults, operand);
      Iterator iResultsIter = intermediateResults.iterator();
      while (iResultsIter.hasNext()) {
        Object tuple = iResultsIter.next();
        if (tuple instanceof Struct) {
          Object values[] = ((Struct) tuple).getFieldValues();
          for (int i = 0; i < values.length; i++) {
            rIters[i].setCurrent(values[i]);
          }
        } else {
          rIters[0].setCurrent(tuple);
        }
        Object result = null;
        try {
          result = operand.evaluate(context);
        } finally {
          observer.afterIterationEvaluation(result);
        }
        if (result instanceof Boolean) {
          if (((Boolean) result).booleanValue())
            resultSet.add(tuple);
        } else if (result != null && result != QueryService.UNDEFINED)
          throw new TypeMismatchException(
              String.format("AND/OR operands must be of type boolean, not type ' %s '",
                  result.getClass().getName()));
      }
    } finally {
      observer.endIteration(resultSet);
    }
    return resultSet;
  }

  /**
   * invariant: all operands are known to be evaluated as a filter no operand organization is
   * necessary
   */
  @Override
  public void negate() {
    _operator = inverseOperator(_operator);
    for (int i = 0; i < _operands.length; i++) {
      if (_operands[i] instanceof Negatable)
        ((Negatable) _operands[i]).negate();
      else
        _operands[i] = new CompiledNegation(_operands[i]);
    }
  }

  @Override
  protected PlanInfo protGetPlanInfo(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    Support.Assert(_operator == LITERAL_or || _operator == LITERAL_and);
    PlanInfo resultPlanInfo = new PlanInfo();
    // set default evalAsFilter depending on operator
    boolean isOr = (_operator == LITERAL_or);
    resultPlanInfo.evalAsFilter = isOr;
    // collect indexes
    // for LITERAL_and operator, if any say yes to filter,
    // then change default evalAsFilter from false to true
    // of LITERAL_or operator, if any say no to filter, change to false
    for (int i = 0; i < _operands.length; i++) {
      PlanInfo opPlanInfo = _operands[i].getPlanInfo(context);
      resultPlanInfo.indexes.addAll(opPlanInfo.indexes);
      if (!isOr && opPlanInfo.evalAsFilter) {
        resultPlanInfo.evalAsFilter = true;
      } else if (isOr && !opPlanInfo.evalAsFilter) {
        resultPlanInfo.evalAsFilter = false;
      }
    }
    return resultPlanInfo;
  }

  /* Package methods */
  @Override
  public int getOperator() {
    return _operator;
  }

  List getOperands() {
    // return unmodifiable copy
    return Collections.unmodifiableList(Arrays.asList(_operands));
  }


  /**
   * TODO: Should composite operands be part of iterator operands of CompiledJunction or should it
   * be part of AllGroupJunction Write a unit Test for this function.
   *
   * Asif: The iterators which can be considered part of GroupJunction are those which are
   * exclusively dependent only on the independent iterator of the group. Any iterator which is
   * ultimately dependent on more than one independent iterators cannot be assumed to be part of the
   * GroupJunction, even if one of independent iterator belongs to a different scope.
   *
   * @return New combination of AbstractCompiledValue(s) in form of CompiledJunction.
   */
  OrganizedOperands organizeOperands(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    // get the list of operands to evaluate, and evaluate operands that can use
    // indexes first.
    List evalOperands = new ArrayList(_operands.length);
    int indexCount = 0;
    // TODO: Check if we can defer the creation of this array list only
    // if there exists an eval operand
    List compositeIterOperands = new ArrayList(_operands.length);
    // Asif: This Map will contain as key the composite filter operand & as
    // value , the set containing independent RuntimeIterators ( which will
    // necessarily be two )
    Map compositeFilterOpsMap = new LinkedHashMap();
    Map iterToOperands = new HashMap();
    CompiledValue operand = null;
    boolean isJunctionNeeded = false;
    boolean indexExistsOnNonJoinOp = false;

    for (int i = 0; i < _operands.length; i++) {
      // Asif : If we are inside this function this itself indicates
      // that there exists at least on operand which can be evaluated
      // as an auxFilterEvaluate. If any operand even if its flag of
      // evalAsFilter happens to be false, but if it is independently
      // evaluable, we should attach it with the auxFilterevaluable
      // operands irrespective of its value ( either true or false.)
      // This is because if it is true or false, it can always be paired
      // up with other filter operands for AND junction. But for
      // OR junction it can get paired with the filterOperands only
      // if it is false. But we do not have to worry about whether
      // the junction is AND or OR because, if the independent operand's
      // value is true & was under an OR junction , it would not have
      // been filterEvaluated. Instead it would have gone for auxIterEvaluate.
      // We are here itself implies, that any independent operand can be
      // either true or false for an AND junction but always false for an
      // OR Junction.
      operand = this._operands[i];
      if (!operand.isDependentOnCurrentScope(context)) {
        indexCount++;
        // Asif Ensure that independent operands are always at the start
        evalOperands.add(0, operand);
      } else if (operand instanceof CompiledJunction) {
        if (operand.getPlanInfo(context).evalAsFilter) {
          // Asif Ensure that independent operands are always at the start
          evalOperands.add(indexCount++, operand);
        } else {
          evalOperands.add(operand);
        }
      } else {
        // If the operand happens to be a Like predicate , this is the point
        // where we can expand as now the structures created are all for the current
        // execution. We expand only if the current junction is AND because if its
        // OR we cannot bring Like at level of OR , because like itself is an AND
        // Also cannot expand for NOT LIKE because CCs generated by CompiledLike with AND
        // will be converted to OR by negation
        CompiledValue expandedOperands[] = null;

        if (operand.getType() == LIKE && this._operator == OQLLexerTokenTypes.LITERAL_and
            && ((CompiledLike) operand).getOperator() != OQLLexerTokenTypes.TOK_NE) {
          expandedOperands =
              ((CompiledLike) operand).getExpandedOperandsWithIndexInfoSetIfAny(context);
        } else {
          expandedOperands = new CompiledValue[] {operand};
        }

        for (CompiledValue expndOperand : expandedOperands) {
          boolean operandEvalAsFilter = expndOperand.getPlanInfo(context).evalAsFilter;
          isJunctionNeeded = isJunctionNeeded || operandEvalAsFilter;
          Set set = QueryUtils.getCurrentScopeUltimateRuntimeIteratorsIfAny(expndOperand, context);
          if (set.size() != 1) {
            // Asif: A set of size not equal to 1 ( which can mean anything more
            // than 1, will mean a composite condition. For a Composite
            // Condition which is filter evaluable that means necessarily that
            // RHS is dependent on one independent iterator & LHS on the other.
            if (operandEvalAsFilter) {
              Support.Assert(set.size() == 2,
                  " The no of independent iterators should be equal to 2");
              compositeFilterOpsMap.put(expndOperand, set);
            } else {
              compositeIterOperands.add(expndOperand);
            }
          } else {
            Support.Assert(set.size() == 1,
                "The size has to be 1 & cannot be zero as that would mean it is independent");
            RuntimeIterator rIter = (RuntimeIterator) set.iterator().next();
            List operandsList = (List) iterToOperands.get(rIter);
            if (operandsList == null) {
              operandsList = new ArrayList();
              iterToOperands.put(rIter, operandsList);
            }
            if (operandEvalAsFilter && _operator == LITERAL_and) {
              indexExistsOnNonJoinOp = true;
            }
            operandsList.add(expndOperand);
          }
        }
      }
    }
    /*
     * Asif : If there exists a SingleGroupJunction & no other Filter operand , then all remaining
     * eval operands ( even if they are CompiledJunction which are not evaluable as Filter) &
     * composite operands should become part of GroupJunction. If there exists only
     * SingleGroupJunction & at least one Filter operand, then all conditions of GroupJunction which
     * are not filter evaluable should become iter operand of CompiledJunction. If there exists an
     * AllGroupJunction & no Filter operand, then all remaining iter operands of CompiledJunction
     * along with Composite operands should be part of AllGroupJunction. If there exists at least
     * one Filter operand , all remaining operands of AllGroupJunction ( including those
     * GroupJunction not filter evaluable should become part of eval operand of CompiledJunction)
     * The index count will give the idea of number of filter operands
     */
    if (isJunctionNeeded) {
      // There exists at least one condition which must have an index available.
      Filter junction = createJunction(compositeIterOperands, compositeFilterOpsMap, iterToOperands,
          context, indexCount, evalOperands, indexExistsOnNonJoinOp);
      // Asif Ensure that independent operands are always at the start
      evalOperands.add(indexCount++, junction);
    } else {
      // if(compositeIterOperands != null) {
      if (!compositeIterOperands.isEmpty()) {
        evalOperands.addAll(compositeIterOperands);
      }
      Iterator itr = iterToOperands.values().iterator();
      while (itr.hasNext()) {
        evalOperands.addAll((List) itr.next());
      }
    }
    OrganizedOperands result = new OrganizedOperands();
    // Group the operands into those that use indexes and those that don't,
    // so we can evaluate all the operands that don't use indexes together in
    // one iteration first get filter operands
    Filter filterOperands = null;
    // there must be at least one filter operand or else we wouldn't be here
    Support.Assert(indexCount > 0);
    if (indexCount == 1) {
      filterOperands = (Filter) evalOperands.get(0);
      result.isSingleFilter = true;
    } else {
      CompiledValue[] newOperands = new CompiledValue[indexCount];
      for (int i = 0; i < indexCount; i++)
        newOperands[i] = (CompiledValue) evalOperands.get(i);
      filterOperands = new CompiledJunction(newOperands, _operator);
    }
    // get iterating operands
    // INVARIANT: the number of iterating operands when the _operator is
    // LITERAL_or must be zero. This is an invariant on filter evaluation
    CompiledValue iterateOperands = null;
    // int numIterating = _operands.length - indexCount;
    int numIterating = evalOperands.size() - indexCount;
    Support.Assert(_operator == LITERAL_and || numIterating == 0);
    if (numIterating > 0) {
      if (numIterating == 1)
        iterateOperands = (CompiledValue) evalOperands.get(indexCount);
      else {
        CompiledValue[] newOperands = new CompiledValue[numIterating];
        for (int i = 0; i < numIterating; i++)
          newOperands[i] = (CompiledValue) evalOperands.get(i + indexCount);
        iterateOperands = new CompiledJunction(newOperands, _operator);
      }
    }
    result.filterOperand = filterOperands;
    result.iterateOperand = iterateOperands;
    return result;
  }

  /**
   * Creates a GroupJunction or a RangeJunction based on the operands passed. The operands are
   * either Filter Operands belonging to single independent RuntimeIterator or are iter evaluable on
   * the RuntimeIterator[] passed as parameter. If all the filter evaluable operands use a single
   * Index , than a RangeJunction is created with iter operand as part of RangeJunction. If there
   * exists operands using multiple indexes, then a GroupJunction is created. In that case , the
   * operands using the same index are grouped in a RangeJunction & that Range Junction becomes part
   * of the GroupJunction. A GroupJunction may contain one or more RangeJunction
   *
   * @param needsCompacting boolean indicating if there is a possibility of RangeJunction or not. If
   *        needsCompacting is false , then a GroupJunction will be formed, without any
   *        RangeJunction
   * @param grpIndpndntItr Array of RuntimeIterator which represents the independent iterator for
   *        the Group. for all cases , except a CompositeGroupJunction containing a single
   *        GroupJunction , will have a single RuntimeIterator in this array.
   * @param completeExpnsn boolean indicating whether the Group or Range Junction needs to be
   *        expanded to the query from clause level or the group level
   * @param cv Array of CompiledValue containing operands belonging to a group
   * @param sameIndexOperands Map object containing Index as the key & as a value an Integer object
   *        or a List. If it contains an Integer as value against Index, it implies that there is
   *        only one operand which uses that type of index & hence cannot form a RangeJunction. If
   *        it contains a List then the Lis contains the operands which use same index & thus can
   *        form a RangeJunction
   * @return Object of GroupJunction or RangeJunction as the case may be
   */
  private AbstractGroupOrRangeJunction createGroupJunctionOrRangeJunction(boolean needsCompacting,
      RuntimeIterator[] grpIndpndntItr, boolean completeExpnsn, CompiledValue[] cv,
      Map sameIndexOperands) {
    AbstractGroupOrRangeJunction junction;
    if (needsCompacting) {
      Iterator itr = sameIndexOperands.values().iterator();
      if (sameIndexOperands.size() == 1) {
        // This means that there exists only one type of Index for the whole
        // Group. Thus overall we should just create a RangeJunction. It also
        // means that the rest of the operands are the Iter Operands ( they may
        // contain those operands which are not index evaluable but evaluate to
        // true/false ( not dependent on current scope)
        List sameIndexOps = (List) itr.next();
        Iterator sameIndexOpsItr = sameIndexOps.iterator();
        for (int i = 0; i < cv.length; ++i) {
          if (cv[i] == null) {
            cv[i] = (CompiledValue) sameIndexOpsItr.next();
          }
        }
        junction = new RangeJunction(this._operator, grpIndpndntItr, completeExpnsn, cv);
      } else {
        int numRangeJunctions = 0;
        CompiledValue[] rangeJunctions = new CompiledValue[sameIndexOperands.size()];
        int nullifiedFields = 0;
        while (itr.hasNext()) {
          Object listOrPosition = itr.next();
          if (listOrPosition instanceof List) {
            List ops = (List) listOrPosition;
            nullifiedFields += ops.size();
            CompiledValue operands[] = (CompiledValue[]) ops.toArray(new CompiledValue[0]);
            rangeJunctions[numRangeJunctions++] =
                new RangeJunction(this._operator, grpIndpndntItr, completeExpnsn, operands);
          }
        }
        int totalOperands = cv.length - nullifiedFields + numRangeJunctions;
        CompiledValue[] allOperands = new CompiledValue[totalOperands];
        // Fill the Non RangeJunction operands first
        int k = 0;
        for (int i = 0; i < cv.length; ++i) {
          CompiledValue tempCV = cv[i];
          if (tempCV != null) {
            allOperands[k++] = tempCV;
          }
        }
        for (int i = 0; i < numRangeJunctions; ++i) {
          allOperands[k++] = rangeJunctions[i];
        }
        junction = new GroupJunction(this._operator, grpIndpndntItr, completeExpnsn, allOperands);
      }
    } else {
      junction = new GroupJunction(this._operator, grpIndpndntItr, completeExpnsn, cv);
    }
    return junction;
  }

  private boolean sortSameIndexOperandsForGroupJunction(CompiledValue cv[], List operandsList,
      Map sameIndexOperands, ExecutionContext context)
      throws AmbiguousNameException, TypeMismatchException, NameResolutionException,
      FunctionDomainException, QueryInvocationTargetException {
    int size = operandsList.size();
    CompiledValue tempOp = null;
    boolean needsCompacting = false;
    for (int i = 0; i < size; ++i) {
      tempOp = (CompiledValue) operandsList.get(i);
      IndexInfo[] indx = null;
      Object listOrPosition = null;
      boolean evalAsFilter = tempOp.getPlanInfo(context).evalAsFilter;
      // TODO:Do not club Like predicate in an existing range
      if (evalAsFilter) {
        indx = ((Indexable) tempOp).getIndexInfo(context);
        // We are now sorting these for joins, therefore we need to weed out the join indexes
        if (!IndexManager.JOIN_OPTIMIZATION || indx.length == 1) {
          Assert.assertTrue(indx.length == 1,
              "There should have been just one index for the condition");
          listOrPosition = sameIndexOperands.get(indx[0]._index);
        }
      }

      if (listOrPosition != null) {
        if (listOrPosition instanceof Integer) {
          int position = ((Integer) listOrPosition).intValue();
          List operands = new ArrayList(size);
          operands.add(cv[position]);
          operands.add(tempOp);
          cv[position] = null;
          sameIndexOperands.put(indx[0]._index, operands);
          needsCompacting = true;
        } else if (listOrPosition instanceof List) {
          List operands = (List) listOrPosition;
          operands.add(tempOp);
        } else {
          // a join was present here, let's now occupy that spot and remove the placeholder
          listOrPosition = null;
        }
      }
      if (listOrPosition == null) {
        cv[i] = tempOp;
        if (indx != null && indx.length == 1) {
          // TODO: Enable only for AND junction for now
          if (evalAsFilter && this._operator == OQLLexerTokenTypes.LITERAL_and) {
            sameIndexOperands.put(indx[0]._index, Integer.valueOf(i));
          }
        } else if (indx != null && indx.length == 2) {
          if (evalAsFilter && this._operator == OQLLexerTokenTypes.LITERAL_and) {
            if (!sameIndexOperands.containsKey(indx[0]._index)) {
              sameIndexOperands.put(indx[0]._index, PLACEHOLDER_FOR_JOIN);
            }
            if (!sameIndexOperands.containsKey(indx[1]._index)) {
              sameIndexOperands.put(indx[1]._index, PLACEHOLDER_FOR_JOIN);
            }
          }
        }
      }
    }
    return needsCompacting;
  }

  // This is called only if the CompiledJunction was either independent or filter evaluable.
  @Override
  public int getSizeEstimate(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    if (this.isDependentOnCurrentScope(context)) {
      return Integer.MAX_VALUE;
    } else {
      return 0;
    }
  }

  // TODO: Optmize this function further in terms of creation of Arrays &
  // Lists
  private Filter createJunction(List compositeIterOperands, Map compositeFilterOpsMap,
      Map iterToOperands, ExecutionContext context, int indexCount, List evalOperands,
      boolean indexExistsOnNonJoinOp) throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    Support.Assert(!(iterToOperands.isEmpty() && compositeFilterOpsMap.isEmpty()),
        " There should not have been any need to create a Junction");
    CompiledValue junction = null;
    int size;
    /*---------- Create only a  GroupJunction */
    if (iterToOperands.size() == 1 && (compositeFilterOpsMap.isEmpty()
        || (indexExistsOnNonJoinOp && IndexManager.JOIN_OPTIMIZATION))) {
      if ((indexExistsOnNonJoinOp && IndexManager.JOIN_OPTIMIZATION)) {
        // For the optimization we will want to add the compositeFilterOpsMap 848
        // without the optimization we only fall into here if it's empty anyways, but have not
        // tested the removal of this if clause
        evalOperands.addAll(compositeFilterOpsMap.keySet());
      }
      // Asif :Create only a GroupJunction. The composite conditions can be
      // evaluated as iter operands inside GroupJunction.
      Map.Entry entry = (Map.Entry) iterToOperands.entrySet().iterator().next();
      List operandsList = (List) entry.getValue();
      // Asif: If there exists no other filter operand, transfer all the
      // remaining iter operands to the Group Junction. Else transfer all the
      // remaining operands to eval operands of CompiledJunctio. This means that
      // we are following the logic that as far as possible minimize the
      // result-set used for iter evaluation of conditions without index.
      // This way we also save on extra iterations for eval conditions if they
      // existed both in GroupJunction as well as CompiledJunction. The only
      // exception in this logic is the iter evaluable conditions belonging to a
      // GroupJunction.
      // If a condition is dependent on a Single Group & is not filter evaluable
      // we do not push it out to iter operands of AllGroupJunction or Compiled
      // Junction , but make it part of GroupJunction itself. This helps bcoz we
      // are sure that the condition will be completely evaluable by the
      // iterators of that group itself.
      if (indexCount == 0) {
        operandsList.addAll(evalOperands);
        evalOperands.clear();
        if (!compositeIterOperands.isEmpty()) {
          operandsList.addAll(compositeIterOperands);
        }
      } else {
        if (!compositeIterOperands.isEmpty()) {
          evalOperands.addAll(compositeIterOperands);
        }
        Iterator itr = operandsList.iterator();
        while (itr.hasNext()) {
          CompiledValue cv = (CompiledValue) itr.next();
          // Asif : Those conditions not filter evaluable are transferred to
          // eval operand of CompiledJunction.
          if (!cv.getPlanInfo(context).evalAsFilter) {
            itr.remove();
            evalOperands.add(cv);
          }
        }
      }
      size = operandsList.size();
      Map sameIndexOperands = new HashMap(size);
      CompiledValue cv[] = new CompiledValue[size];
      // Enable only for AND junction
      boolean needsCompacting =
          sortSameIndexOperandsForGroupJunction(cv, operandsList, sameIndexOperands, context);
      junction = createGroupJunctionOrRangeJunction(needsCompacting,
          new RuntimeIterator[] {(RuntimeIterator) entry.getKey()},
          true /* need a Complete expansion */, cv, sameIndexOperands);
    }
    /*
     * Asif : An AllGroupJunction or a CompositeGroupJunction can get created. An AllGroupJunction
     * will get created , if there exists a need to create more than one CompositeGroupJunction
     * AND/OR more than one GroupJunctions ( not part of CompositeGroupJunction) If suppose the
     * where clause contained two sets of conditions each dependent exclusively on a separate
     * independent group ( implying two independent groups) then we should create an
     * AllGroupJunction iff the two Groups are both filter evaluable. If an AllGroupJunction
     * contains only one filter evaluable Group & no CompositeGroupJunction then we should just
     * create a singleGroupJunction with complete expansion as true
     */
    else {
      // Asif : First create the required amount of CompositeGroupJunctions
      // A map which keeps track of no. of independent iterators pointing to the
      // same CompositeGroupJunction. The integer count will keep track of
      // number of different CompositeGroupJunctions which got created.
      Map tempMap = new HashMap();
      Set entries = compositeFilterOpsMap.entrySet();
      Set cgjs = new HashSet(compositeFilterOpsMap.size());
      Iterator entryItr = entries.iterator();
      while (entryItr.hasNext()) {
        Map.Entry entry = (Map.Entry) entryItr.next();
        CompiledValue op = (CompiledValue) entry.getKey();
        Set indpndtItrSet = (Set) entry.getValue();
        Iterator itr = indpndtItrSet.iterator();
        CompositeGroupJunction cgj = null;
        RuntimeIterator[] absentItrs = new RuntimeIterator[2];
        int k = 0;
        while (itr.hasNext()) {
          RuntimeIterator ritr = (RuntimeIterator) itr.next();
          CompositeGroupJunction temp = (CompositeGroupJunction) tempMap.get(ritr);
          if (temp == null) {
            absentItrs[k++] = ritr;
          }
          if (cgj == null && temp != null) {
            cgj = temp;
            cgj.addFilterableCompositeCondition(op);
          } else if (cgj != null && temp != null && cgj != temp) {
            // Asif A peculiar case wherein we have some thing like four regions
            // with relation ship conditions like r1 = r2 and r3 = r4 and r4 =
            // r1. In such situations we should just have a single
            // CompositeJunction containing r1 r2 r3 and r4 We will merge temp
            // into CompositeGroupJunction & change all the values in tempMap
            // which contained temp object to CompositeGroupJunction.
            // Also we will remove the entry of temp from CompositeGroupJunctions.
            cgj.mergeFilterableCCsAndIndependentItrs(temp);
            cgjs.remove(temp);
            Iterator entriesItr = tempMap.entrySet().iterator();
            Map.Entry tempEntry = null;
            while (entriesItr.hasNext()) {
              tempEntry = (Map.Entry) entriesItr.next();
              if (tempEntry.getValue() == temp) {
                tempEntry.setValue(cgj);
              }
            }
          }
        }
        if (cgj == null) {
          // Asif Create a new CompositeGroupJunction
          cgj = new CompositeGroupJunction(this._operator, op /* CompositeFilterOperand */);
          cgjs.add(cgj);
        }
        for (int i = 0; i < k; ++i) {
          tempMap.put(absentItrs[i], cgj);
          cgj.addIndependentIterators(absentItrs[i]);
        }
      }
      // Asif :If no of cgj is zero definitely there will be an AllGroupJunction
      // If no. of cgj is more than 1 , then also there will be an AllGroupJunction.
      // But if no. of cgj is excactly one & all the GroupJunctions can be
      // accomodated within the CGJ , then we will have CompsiteGroupJunction.
      // Also , those composite conditions which are not filter evaluable will
      // be added to CompositeGroupJunction as iter operands only if we don't
      // have any additional filter & CompositeGroupJunction is the only
      // junction which will get created. If there exists any other filter then
      // it will be part of CompiledJunction's iter operand. Basically we will
      // not distinguish between various CompositeConditions which are not
      // filter evaluable & will not try to place it in various
      // ComspoiteGroupJunctions to which they belong.
      List gjs = new ArrayList(iterToOperands.size());
      Iterator itr = iterToOperands.entrySet().iterator();
      Map.Entry entry;
      while (itr.hasNext()) {
        entry = (Map.Entry) itr.next();
        List operandsList = (List) entry.getValue();
        CompiledValue cv[] = new CompiledValue[size = operandsList.size()];
        int j = 0;
        // Asif:An individual GroupJunction is Filter evaluable if at least one
        // operand is filter evaluable.
        boolean evalAsFilter = false;
        boolean needsCompacting = false;
        CompiledValue tempOp = null;
        Map sameIndexOperands = new HashMap(size);

        for (; j < size; ++j) {
          tempOp = (CompiledValue) operandsList.get(j);
          boolean isFilterevaluable = tempOp.getPlanInfo(context).evalAsFilter;
          evalAsFilter = evalAsFilter || isFilterevaluable;
          IndexInfo[] indx = null;
          Object listOrPosition = null;
          if (isFilterevaluable) {
            indx = ((Indexable) tempOp).getIndexInfo(context);
            Assert.assertTrue(indx.length == 1,
                "There should have been just one index for the condition");
            listOrPosition = sameIndexOperands.get(indx[0]._index);
          }
          if (listOrPosition != null) {
            if (listOrPosition instanceof Integer) {
              int position = ((Integer) listOrPosition).intValue();
              List operands = new ArrayList(size);
              operands.add(cv[position]);
              operands.add(tempOp);
              cv[position] = null;
              sameIndexOperands.put(indx[0]._index, operands);
              needsCompacting = true;
            } else {
              List operands = (List) listOrPosition;
              operands.add(tempOp);
            }
          } else {
            cv[j] = tempOp;
            if (isFilterevaluable && this._operator == OQLLexerTokenTypes.LITERAL_and) {
              sameIndexOperands.put(indx[0]._index, Integer.valueOf(j));
            }
          }
        }
        if (!evalAsFilter) {
          // Asif : If there exists at least one Filter then those GroupJunction
          // which are not Filter evaluable should become part of eval operands
          // of CompiledJunction else add the Group operands which is not filter
          // evaluable to the Composite iterator oprands
          List toAddTo = null;
          if (indexCount > 0) {
            toAddTo = evalOperands;
          } else {
            toAddTo = compositeIterOperands;
          }
          for (int i = 0; i < size; ++i) {
            toAddTo.add(cv[i]);
          }
        } else {
          RuntimeIterator grpIndpndtItr = (RuntimeIterator) entry.getKey();
          AbstractGroupOrRangeJunction gj = createGroupJunctionOrRangeJunction(needsCompacting,
              new RuntimeIterator[] {(RuntimeIterator) entry.getKey()},
              false/* Expand only to Group Level */, cv, sameIndexOperands);
          CompositeGroupJunction cgj = null;
          if ((cgj = (CompositeGroupJunction) tempMap.get(grpIndpndtItr)) != null) {
            cgj.addGroupOrRangeJunction(gj);
          } else {
            gjs.add(gj);
          }
        }
      }
      if (indexCount == 0) {
        // Asif : all the eval operands of CompiledJunction should be part of
        // AllGroupJunction
        compositeIterOperands.addAll(evalOperands);
        evalOperands.clear();
      } else {
        // Asif : Add the composite operands to the eval operands so that they
        // are evaluated as part of CompiledJunction.
        if (!compositeIterOperands.isEmpty()) {
          evalOperands.addAll(compositeIterOperands);
        }
      }
      // Asif : An AllGroupJunction will be created iff either the List
      // containing GroupJunctions is not empty ot there exists multiple
      // CompositeGroupJunctions Else a CompositeGroupJunction will be created
      // Convert the List of Indpendent Runtime Iterators of
      // CompositeGroupJunction into Array of Indpendent RuntimeIterators
      Iterator cgjItr = cgjs.iterator();
      while (cgjItr.hasNext()) {
        ((CompositeGroupJunction) cgjItr.next()).setArrayOfIndependentItrs();
      }
      int cgjSize = cgjs.size();
      if (gjs.isEmpty() && cgjSize == 1) {
        CompositeGroupJunction compGrpJnc = (CompositeGroupJunction) cgjs.iterator().next();
        compGrpJnc.addIterOperands(compositeIterOperands);
        compGrpJnc.setCompleteExpansionOn();
        junction = compGrpJnc;
      } else if (gjs.size() == 1 && cgjSize == 0) {
        // Asif: There exists only a single Filterable GroupJunction & no
        // CompositeGroupJunction so we should just create a GroupJunction
        // instead of an AllGroupJunction . ( In this way the remaining iter
        // operands will get evaluated during the filter evaluation of
        // GroupJunction) For such GroupJunction complete expansion needs to be
        // true & the list of composite iter operands ( which at this point
        // contains the iter operands, should be added to the operands of
        // GroupJunction where they will get orgainzed as iter operands during
        // the call of organizeOperands in GroupJunction
        AbstractGroupOrRangeJunction gjTemp = (AbstractGroupOrRangeJunction) gjs.get(0);
        compositeIterOperands.addAll(gjTemp.getOperands());
        CompiledValue newOps[] = new CompiledValue[compositeIterOperands.size()];
        compositeIterOperands.toArray(newOps);
        // Asif : If gjTemp is a RangeJunction, we will get an instance of
        // RangeJunction else we will get an instance of GroupJunction.
        junction =
            gjTemp.createNewOfSameType(this._operator, gjTemp.getIndependentIteratorForGroup(),
                true/* The expansion needs to be complete */, newOps);

      } else {
        gjs.addAll(cgjs);
        junction = new AllGroupJunction(gjs, this._operator, compositeIterOperands);
      }
    }
    return (Filter) junction;
  }

  // Asif : This function provides package visbility for testing the
  // output of organizeOperands function.
  OrganizedOperands testOrganizedOperands(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    return organizeOperands(context);
  }

  @Override
  public boolean isProjectionEvaluationAPossibility(ExecutionContext context)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    for (int i = 0; i < this._operands.length; ++i) {
      // LIKE gives rise to a JUNCTION in CompiledLike whether wildcard is present or not
      if ((this._operands[i].getType() == JUNCTION || this._operands[i].getType() == LIKE)
          && this._operands[i].getPlanInfo(context).evalAsFilter) {
        return false;
      }
    }
    return true;
  }

  /*
   * This method checks the limit applicability on index intermediate results for junctions and
   * optimizes the limit on index intermediate results ONLY if ONE index is used for whole query and
   * all conditions in where clause use that index. Look at the call hierarchy of this function.
   * There are two cases:
   *
   * Literal_OR: A junction with OR will contain operands which are CompiledComparison or
   * CompiledJunction (or subjunction). we recursively check if all of those use the same index and
   * if ANY one of those comparisons or subjunctions does not use the index, it retruns false.
   *
   * Literal_AND: If we get combination of comparisons and subjunctions then limit is NOT applicable
   * on index results. Like, "where ID != 10 AND (ID < 5 OR ID > 10) LIMIT 5". If we get only
   * comparisons ONLY then if all comparisons use the same index then limit is applicable and this
   * returns true. Like, "where ID != 10 AND (ID < 5 AND ID > 10) LIMIT 5".
   *
   */
  @Override
  public boolean isLimitApplicableAtIndexLevel(ExecutionContext context)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    if (this._operator == LITERAL_or) {
      // There is a slight inefficiency in the sense that if the subjunction ( say AND) cannot apply
      // limit,
      // then limit would not be applied at remaining conditions of OR. But since we have single
      // flag
      // governing the behaviour of applying limit at index level, we cannot make it true for
      // specific clauses
      for (int i = 0; i < this._operands.length; ++i) {
        if (!this._operands[i].getPlanInfo(context).evalAsFilter
            || ((Filter) this._operands[i]).isLimitApplicableAtIndexLevel(context)) {
          return false;
        }
      }
      return true;
    } else {
      // For limit to be applicable on a AND junction, there should be only one type of index used
      // and rest iter evaluable
      // But since the selection of which index to use happens in GroupJunction created at runtimke,
      // we do not have that
      // information yet, and at this point there would be multiple indexes. Ideally we should
      // invoke this function in GroupJunction,
      // in case we want to support multi index usage again at some point. Till then since it is
      // hard coded to use 1 index
      // we can for the time being return true if there exists atleast one indexable condition
      boolean foundIndex = false;
      for (int i = 0; i < this._operands.length; ++i) {
        if (this._operands[i].getPlanInfo(context).evalAsFilter
            && this._operands[i].getType() == JUNCTION) {
          return false;
        } else if (this._operands[i].getPlanInfo(context).evalAsFilter) {
          foundIndex = true;
        }
      }
      return foundIndex;
    }
  }

  @Override
  public boolean isOrderByApplicableAtIndexLevel(ExecutionContext context,
      String canonicalizedOrderByClause) throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    if (this._operator == LITERAL_and) {
      // Set<IndexProtocol> usedIndex = new HashSet<IndexProtocol>();
      boolean foundRightIndex = false;
      for (int i = 0; i < this._operands.length; ++i) {
        PlanInfo pi = this._operands[i].getPlanInfo(context);
        if (pi.evalAsFilter && this._operands[i].getType() == JUNCTION) {
          return false;
        } else if (pi.evalAsFilter) {
          if (!foundRightIndex) {
            IndexProtocol ip =
                (IndexProtocol) this._operands[i].getPlanInfo(context).indexes.get(0);
            if (ip.getCanonicalizedIndexedExpression().equals(canonicalizedOrderByClause)
                && pi.isPreferred) {
              foundRightIndex = true;
            }
          }
          // usedIndex.addAll(this._operands[i].getPlanInfo(context).indexes);
        }
      }
      return foundRightIndex;
      // if(usedIndex.size() == 1 &&
      // usedIndex.iterator().next().getCanonicalizedIndexedExpression().equals(canonicalizedOrderByClause))
      // {
      // return true;
      // }
    }
    return false;
  }

  /*
   * class CGJData { RuntimeIterator [] indpndItrs = null; List iterOperands = null; List
   * groupJunctions = null; CompiledValue [] compositeCompiledComparisons = null;
   *
   * CGJData(RuntimeIterator [] indpndItrs, List iterOperands,List groupJunctions, CompiledValue []
   * compositeCompiledComparisons) { this.indpndItrs = indpndItrs; this.iterOperands = iterOperands;
   * this.groupJunctions = groupJunctions; this.compositeCompiledComparisons =
   * compositeCompiledComparisons; } }
   */
}
