/*
 * 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.
 */
/*
 * Created on Nov 15, 2005
 *
 * TODO To change the template for this generated file go to Window - Preferences - Java - Code
 * Style - Code Templates
 */
package org.apache.geode.cache.query.internal;

import static org.apache.geode.cache.Region.SEPARATOR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.LogWriter;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.CacheUtils;
import org.apache.geode.cache.query.IndexType;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.data.Address;
import org.apache.geode.cache.query.data.Employee;
import org.apache.geode.cache.query.data.Portfolio;
import org.apache.geode.cache.query.internal.index.IndexManager;
import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.test.junit.categories.OQLQueryTest;

@Category({OQLQueryTest.class})
public class CompiledJunctionInternalsJUnitTest {

  Region region;
  QueryService qs;

  @Before
  public void setUp() throws Exception {
    CacheUtils.startCache();
    region = CacheUtils.createRegion("portfolio", Portfolio.class);
    region.put("0", new Portfolio(0));
    region.put("1", new Portfolio(1));
    region.put("2", new Portfolio(2));
    region.put("3", new Portfolio(3));
    qs = CacheUtils.getQueryService();
  }

  /*************************************************
   * AND JUNCTION TESTS. RangeJunction related tests when part of GroupJunction,
   * CompositeGroupJunction or AllGroupJunction
   **************************************************/

  // Case 1: When a Single GroupJunction contains multiple
  // RangeJunctionEvaluators for AND
  @Test
  public void testMultipleRangeJunctionsInAGroupJunction() {
    QCompiler compiler = new QCompiler();
    List list = compiler.compileFromClause(SEPARATOR + "portfolio p, p.positions");
    ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
    context.newScope(context.associateScopeID());
    try {
      qs.createIndex("statusIndex", IndexType.FUNCTIONAL, "status", SEPARATOR + "portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }

      // case id > 7 and id < 10 and status > abc and status < xyz
      CompiledComparison[] cv = new CompiledComparison[4];

      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(7), OQLLexerTokenTypes.TOK_GT);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("abc"), OQLLexerTokenTypes.TOK_GT);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_LT);
      cv[3] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("xyz"), OQLLexerTokenTypes.TOK_LT);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("The Organized operand object is null", oo);
      assertTrue("Filter Operand  did not happen to be an instance of GroupJunction",
          oo.filterOperand instanceof GroupJunction);
      assertNull("Iterate Operand  not coming out to be null", oo.iterateOperand);
      assertTrue("The Conditions in GroupJunction not equal to 2",
          ((GroupJunction) oo.filterOperand).getOperands().size() == 2);
      GroupJunction gj = (GroupJunction) oo.filterOperand;
      assertTrue(gj.getOperands().get(0) instanceof RangeJunction);
      assertTrue(gj.getOperands().get(1) instanceof RangeJunction);
      RangeJunction r1 = (RangeJunction) gj.getOperands().get(0);
      RangeJunction r2 = (RangeJunction) gj.getOperands().get(1);
      assertEquals(2, r1._operands.length);
      assertEquals(2, r2._operands.length);
      OrganizedOperands oo2 = r1.organizeOperands(context);
      assertTrue(RangeJunction.isInstanceOfDoubleCondnRangeJunctionEvaluator(oo2.filterOperand));
      oo2 = r2.organizeOperands(context);
      assertTrue(RangeJunction.isInstanceOfDoubleCondnRangeJunctionEvaluator(oo2.filterOperand));

    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }


  // Case 2: When a Single GroupJunction contains multiple
  // RangeJunctions and a sinlge indexable compiledcomparison for AND
  @Test
  public void testMultipleRangeJunctionsAndAnIndexableConditionInAGroupJunction() {
    QCompiler compiler = new QCompiler();
    List list = compiler.compileFromClause(SEPARATOR + "portfolio p, p.positions");
    ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
    context.newScope(context.associateScopeID());
    try {
      qs.createIndex("statusIndex", IndexType.FUNCTIONAL, "status", SEPARATOR + "portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      qs.createIndex("createTime", IndexType.FUNCTIONAL, "createTime", SEPARATOR + "portfolio");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }

      // case id > 7 and id < 10 and status > abc and status < xyz and
      // createTime >7
      CompiledComparison[] cv = new CompiledComparison[5];

      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(7), OQLLexerTokenTypes.TOK_GT);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("abc"), OQLLexerTokenTypes.TOK_GT);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_LT);
      cv[3] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("xyz"), OQLLexerTokenTypes.TOK_LT);
      cv[4] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "createTime"),
          new CompiledLiteral(7), OQLLexerTokenTypes.TOK_GT);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("The Organized operand object is null", oo);
      assertTrue("Filter Operand  did not happen to be an instance of GroupJunction",
          oo.filterOperand instanceof GroupJunction);
      assertNull("Iterate Operand  not coming out to be null", oo.iterateOperand);
      assertTrue("The Conditions in GroupJunction not equal to 3",
          ((GroupJunction) oo.filterOperand).getOperands().size() == 3);
      GroupJunction gj = (GroupJunction) oo.filterOperand;
      CompiledValue[] ops = gj._operands;
      int index = -1;
      int one = -1;
      int two = -1;
      if (ops[0] == cv[4]) {
        index = 0;
        one = 1;
        two = 2;
      } else if (ops[1] == cv[4]) {
        index = 1;
        one = 0;
        two = 2;
      } else if (ops[2] == cv[4]) {
        index = 2;
        one = 0;
        two = 1;
      } else {
        fail("Missing single condition");
      }
      assertTrue(ops[index] == cv[4]);
      assertTrue(ops[one] instanceof RangeJunction);
      assertTrue(ops[two] instanceof RangeJunction);

      RangeJunction r1 = (RangeJunction) gj._operands[one];
      RangeJunction r2 = (RangeJunction) gj._operands[two];
      assertEquals(2, r1._operands.length);
      assertEquals(2, r2._operands.length);
      OrganizedOperands oo2 = r1.organizeOperands(context);
      assertTrue(RangeJunction.isInstanceOfDoubleCondnRangeJunctionEvaluator(oo2.filterOperand));
      oo2 = r2.organizeOperands(context);
      assertTrue(RangeJunction.isInstanceOfDoubleCondnRangeJunctionEvaluator(oo2.filterOperand));

    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }

  // Case 3: A Composite GroupJunction containing just a single RangeJunction
  // FOR AND clause. In such case a CompisteGroupJunction should contain a
  // GroupJunction and the GroupJunction should contain a CompiledJunction as
  // iter operand
  // portfolio.id= employee.id and p.id > 3 and p.id <10 and p.status =active
  // and p.type=abc
  // and emp.age = 1
  @Test
  public void testSingleRangeJunctionInACompositeGroupJunction() {
    try {
      Region r3 = CacheUtils.createRegion("employees", Employee.class);
      Set add1 = new HashSet();
      add1.add(new Address("411045", "Baner"));
      add1.add(new Address("411001", "DholePatilRd"));
      for (int i = 0; i < 4; i++) {
        r3.put(i + "", new Employee("empName", (20 + i), i, "Mr.", (5000 + i), add1));
      }
      // compileFromClause returns a List<CompiledIteratorDef>
      QCompiler compiler = new QCompiler();
      List list = compiler
          .compileFromClause(SEPARATOR + "portfolio p, p.positions," + SEPARATOR + "employees e");
      ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
      context.newScope(context.associateScopeID());

      // qs.createIndex("statusIndex",
      // IndexType.FUNCTIONAL,"status","/portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      qs.createIndex("empid", IndexType.FUNCTIONAL, "empId", SEPARATOR + "employees");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[6];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("e"), "age"),
          new CompiledLiteral(1), OQLLexerTokenTypes.TOK_EQ);
      cv[3] = new CompiledComparison(new CompiledPath(new CompiledID("e"), "empId"),
          new CompiledPath(new CompiledID("p"), "ID"), OQLLexerTokenTypes.TOK_EQ);
      cv[4] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(3), OQLLexerTokenTypes.TOK_GT);
      cv[5] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_LT);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("OO is null", oo);
      assertTrue("Filter operand of OO not CompositeGroupJunction",
          oo.filterOperand instanceof CompositeGroupJunction);
      CompositeGroupJunction cgj = (CompositeGroupJunction) oo.filterOperand;
      List filterableCC = cgj.getFilterableCCList();
      assertTrue("No. of filterable CC  not equal to 1", filterableCC.size() == 1);
      assertNotNull("1 RangeJunction inside CompositeGroupJunction should have existed",
          cgj.getGroupJunctionList());
      assertTrue(" Complete expansion flag should have been true", cgj.getExpansionFlag());
      assertNotNull("Iter operands list in CGJ should  be not null", cgj.getIterOperands());
      List ietrOps = cgj.getIterOperands();
      assertTrue(ietrOps.contains(cv[2]));
      assertTrue(cgj.getGroupJunctionList().size() == 1);
      assertTrue(cgj.getGroupJunctionList().get(0) instanceof RangeJunction);
      RangeJunction rg = (RangeJunction) cgj.getGroupJunctionList().get(0);
      OrganizedOperands oo1 = rg.organizeOperands(context);
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[0]));
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[1]));
      assertTrue(RangeJunction.isInstanceOfDoubleCondnRangeJunctionEvaluator(oo1.filterOperand));
      assertTrue(RangeJunction.getDoubleCondnEvaluatorGreaterKey(oo1.filterOperand)
          .equals(3));
      assertTrue(
          RangeJunction.getDoubleCondnEvaluatorLESSKey(oo1.filterOperand).equals(10));
      /*
       * assertTrue( " The size of itr operands should be 3 but size happens to be = " +
       * cgj.getIterOperands().size(), cgj.getIterOperands().size() == 3);
       */
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }

  /**
   * Tests that the organized operands work correctly whether it is multiple GroupJunctions as part
   * of AllGroupJunction or a RangeJunction and GroupJunction. Since where previously it used to be
   * only Group can now be Group or Range , the source code needs to ensure that it does not type
   * cast wrongly a RangeJunction into a GroupJunction. Instead the source code should only type
   * cast it to AbstractGroupOrRangeJunction Case p.status = active and p.type = type1 and emp.id
   * >10 and p.id > 10 and p.id > 15
   */
  @Test
  public void testMultipleIndependentRegionsWithOnlyOneRegionHavingFilterEvaluatableCondition() {
    // Here there will be a single RangeJunction with the iter evaluatable
    // conditions of the other
    // independent iterator becoming the part of this single RangeJunction
    try {
      Region r3 = CacheUtils.createRegion("employees", Employee.class);
      Set add1 = new HashSet();
      add1.add(new Address("411045", "Baner"));
      add1.add(new Address("411001", "DholePatilRd"));
      for (int i = 0; i < 4; i++) {
        r3.put(i + "", new Employee("empName", (20 + i), i, "Mr.", (5000 + i), add1));
      }
      // compileFromClause returns a List<CompiledIteratorDef>
      QCompiler compiler = new QCompiler();
      List list = compiler
          .compileFromClause(SEPARATOR + "portfolio p, p.positions," + SEPARATOR + "employees e");
      ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
      context.newScope(context.associateScopeID());
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio p");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[5];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);

      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("e"), "empId"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_GT);
      cv[3] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_GT);
      cv[4] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(15), OQLLexerTokenTypes.TOK_GT);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("OO is null", oo);
      assertTrue("Filter operand of OO not a RangeJunction",
          oo.filterOperand instanceof RangeJunction);
      RangeJunction rj = (RangeJunction) oo.filterOperand;
      OrganizedOperands oo1 = rj.organizeOperands(context);
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[0]));
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[1]));
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[2]));
      assertTrue(oo1.filterOperand == cv[4]);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }

  /**
   * Tests that the organized operands work correctly whether it is multiple GroupJunctions as part
   * of AllGroupJunction or a RangeJunction and GroupJunction. Since where previously it used to be
   * only Group can now be Group or Range , the source code needs to ensure that it does not type
   * cast wrongly a RangeJunction into a GroupJunction. Instead the source code should only type
   * cast it to AbstractGroupOrRangeJunction Case p.status = active and p.type = type1 and emp.id
   * >10 and p.id > 10 and p.id > 15
   */
  @Test
  public void testMultipleIndependentRegionsWithRangeJunction() {

    try {
      Region r3 = CacheUtils.createRegion("employees", Employee.class);
      Set add1 = new HashSet();
      add1.add(new Address("411045", "Baner"));
      add1.add(new Address("411001", "DholePatilRd"));
      for (int i = 0; i < 4; i++) {
        r3.put(i + "", new Employee("empName", (20 + i), i, "Mr.", (5000 + i), add1));
      }
      // compileFromClause returns a List<CompiledIteratorDef>
      QCompiler compiler = new QCompiler();
      List list = compiler
          .compileFromClause(SEPARATOR + "portfolio p, p.positions," + SEPARATOR + "employees e");
      ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
      context.newScope(context.associateScopeID());

      // qs.createIndex("statusIndex",
      // IndexType.FUNCTIONAL,"status","/portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio p");
      qs.createIndex("empid", IndexType.FUNCTIONAL, "empId", SEPARATOR + "employees e");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[5];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);

      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("e"), "empId"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_GT);
      cv[3] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(10), OQLLexerTokenTypes.TOK_GT);
      cv[4] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(15), OQLLexerTokenTypes.TOK_GT);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("OO is null", oo);
      assertTrue("Filter operand of OO not AllGroupJunction",
          oo.filterOperand instanceof AllGroupJunction);
      AllGroupJunction agj = (AllGroupJunction) oo.filterOperand;
      List filterableCC = agj.getGroupOperands();
      assertTrue(agj.getIterOperands().isEmpty());
      assertTrue(agj.getGroupOperands().size() == 2);
      assertTrue(agj.getGroupOperands().get(0) instanceof GroupJunction
          || agj.getGroupOperands().get(1) instanceof GroupJunction);
      assertTrue(agj.getGroupOperands().get(0) instanceof RangeJunction
          || agj.getGroupOperands().get(1) instanceof RangeJunction);
      RangeJunction rj = null;
      if (agj.getGroupOperands().get(0) instanceof RangeJunction) {
        rj = (RangeJunction) agj.getGroupOperands().get(0);
      } else {
        rj = (RangeJunction) agj.getGroupOperands().get(1);
      }

      OrganizedOperands oo1 = rj.organizeOperands(context);
      assertTrue(oo1.filterOperand == cv[4]);
      assertNotNull(oo1.iterateOperand);
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[0]));
      assertTrue(((CompiledJunction) oo1.iterateOperand).getOperands().contains(cv[1]));
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }

  }

  /** ********************************************************************** */
  // Asif: Since this is a single region & part fropm Group Junction
  // no other filter is there , we shoudl get a SingleGroupJucntion as
  // filter operand of CompiledJunction & not iter operand in Compiled
  // Juncion
  @Test
  public void testOrganizedOperandsSingleGroupJunctionSingleFilter() {
    // compileFromClause returns a List<CompiledIteratorDef>
    QCompiler compiler = new QCompiler();
    List list = compiler.compileFromClause(SEPARATOR + "portfolio p, p.positions");
    ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
    context.newScope(context.associateScopeID());
    try {
      qs.createIndex("statusIndex", IndexType.FUNCTIONAL, "status", SEPARATOR + "portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[3];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(2), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("The Organized operand object is null", oo);
      assertTrue("Filter Operand  did not happen to be an instance of GroupJunction",
          oo.filterOperand instanceof GroupJunction);
      assertNull("Iterate Operand  not coming out to be null", oo.iterateOperand);
      assertTrue("The Conditions in GroupJunction not equal to 3",
          ((GroupJunction) oo.filterOperand).getOperands().size() == 3);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }

  // Asif: Since this is a single region & apart from GroupJunction
  // there exists another filter , We shoudl get two Filter operands
  // One as GroupJunction & the other one the other Filter operand.
  // The un indexed condition should become part of iter operand
  // of CompiledJunction
  @Test
  public void testOrganizedOperandsSingleGroupJunctionMultipleFilter() {
    // compileFromClause returns a List<CompiledIteratorDef>
    QCompiler compiler = new QCompiler();
    List list = compiler.compileFromClause(SEPARATOR + "portfolio p, p.positions");
    ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
    context.newScope(context.associateScopeID());
    try {
      qs.createIndex("statusIndex", IndexType.FUNCTIONAL, "status", SEPARATOR + "portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[4];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(2), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);
      cv[3] = new CompiledComparison(new CompiledLiteral(Boolean.TRUE),
          new CompiledLiteral(Boolean.TRUE), OQLLexerTokenTypes.TOK_EQ);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("OrganizedOperand object is null", oo);
      assertTrue("Filter Openad of OrganizedOperand is not of type CompiledJunction",
          oo.filterOperand instanceof CompiledJunction);
      CompiledJunction temp = (CompiledJunction) oo.filterOperand;
      List operands = temp.getOperands();
      assertTrue("The number of Filter operands not coming to be 2", operands.size() == 2);
      assertTrue(
          "The independent operand shoudl be the first operand of the set of Filter Operands",
          operands.get(0) == cv[3]);
      assertTrue(operands.get(1) instanceof GroupJunction);
      List temp1 = ((GroupJunction) operands.get(1)).getOperands();
      assertTrue("The number & nature of CompiledComparison of Group Junction not as expected",
          temp1.get(0) == cv[0]);
      assertTrue("The number & nature of CompiledComparison of Group Junction not as expected",
          temp1.get(1) == cv[1]);
      assertNotNull("The iter operand of OO is null", oo.iterateOperand);
      assertTrue("IterOperand of OO not as expectd", oo.iterateOperand == cv[2]);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed sue to Exception = " + e);
    }
  }

  // Asif: There are two regions in query but since the conditions in where
  // clause
  // pertain to single region , we still will have a GroupJunction as a filter
  // operand.
  // Since there is only One Filter condition , we should have iter operand
  // as null;
  @Test
  public void testOrganizedOperandsGroupJunctionSingleFilterDoubleRegion() {
    try {
      Region r3 = CacheUtils.createRegion("employees", Employee.class);
      Set add1 = new HashSet();
      add1.add(new Address("411045", "Baner"));
      add1.add(new Address("411001", "DholePatilRd"));
      for (int i = 0; i < 4; i++) {
        r3.put(i + "", new Employee("empName", (20 + i), i, "Mr.", (5000 + i), add1));
      }
      // compileFromClause returns a List<CompiledIteratorDef>
      QCompiler compiler = new QCompiler();
      List list = compiler
          .compileFromClause(SEPARATOR + "portfolio p, p.positions," + SEPARATOR + "employees e");
      ExecutionContext context = new QueryExecutionContext(null, CacheUtils.getCache());
      context.newScope(context.associateScopeID());

      qs.createIndex("statusIndex", IndexType.FUNCTIONAL, "status", SEPARATOR + "portfolio");
      qs.createIndex("idIndex", IndexType.FUNCTIONAL, "ID", SEPARATOR + "portfolio");
      for (final Object o : list) {
        CompiledIteratorDef iterDef = (CompiledIteratorDef) o;
        context.addDependencies(new CompiledID("dummy"), iterDef.computeDependencies(context));
        RuntimeIterator rIter = iterDef.getRuntimeIterator(context);
        context.bindIterator(rIter);
        context.addToIndependentRuntimeItrMap(iterDef);
      }
      CompiledComparison[] cv = new CompiledComparison[3];
      cv[0] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "ID"),
          new CompiledLiteral(2), OQLLexerTokenTypes.TOK_EQ);
      cv[1] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "status"),
          new CompiledLiteral("active"), OQLLexerTokenTypes.TOK_EQ);
      cv[2] = new CompiledComparison(new CompiledPath(new CompiledID("p"), "type"),
          new CompiledLiteral("type1"), OQLLexerTokenTypes.TOK_EQ);
      CompiledJunction cj = new CompiledJunction(cv, OQLLexerTokenTypes.LITERAL_and);
      context.addDependencies(new CompiledID("dummy"), cj.computeDependencies(context));
      cj.getPlanInfo(context);
      OrganizedOperands oo = cj.testOrganizedOperands(context);
      assertNotNull("OO turning out to be null", oo);
      assertTrue("Filter operand of OO not a GroupJunction",
          oo.filterOperand instanceof GroupJunction);
      GroupJunction temp = (GroupJunction) oo.filterOperand;
      List operands = temp.getOperands();
      assertTrue("No. of conditions in Group Junction not as expected of size 3",
          operands.size() == 3);
      assertNull("The iter operand of OO should have bee null", oo.iterateOperand);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Test failed due to Exception = " + e);
    }
  }

  // Asif: There are two regions in query with a equi join condition. The other
  // conditions do not have index
  // on them. In such case we should have single CompositeGroupJunction . The
  // filterable cc list
  // size should be 1.
  @Test
  public void testOrganizedOperandsSingleCompositeGroupJunctionSingleFilterDoubleRegionWithNoGroupJunction() {
    try {
      Region r3 = CacheUtils.createRegion("employees", Employee.class);
      Set add1 = new HashSet();
      add1.add(new Address("411045", "Baner"));
      add1.add(new Address("411001", "DholePatilRd"));
      for (int i = 0; i < 4; i++) {
