/*
 * 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.accumulo.examples.wikisearch.iterator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Set;

import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.IteratorEnvironment;
import org.apache.accumulo.core.iterators.OptionDescriber;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.examples.wikisearch.parser.JexlOperatorConstants;
import org.apache.accumulo.examples.wikisearch.parser.QueryParser;
import org.apache.accumulo.examples.wikisearch.parser.QueryParser.QueryTerm;
import org.apache.accumulo.examples.wikisearch.parser.RangeCalculator.RangeBounds;
import org.apache.accumulo.examples.wikisearch.parser.TreeNode;
import org.apache.accumulo.examples.wikisearch.util.FieldIndexKeyParser;
import org.apache.commons.jexl2.parser.ASTAndNode;
import org.apache.commons.jexl2.parser.ASTEQNode;
import org.apache.commons.jexl2.parser.ASTERNode;
import org.apache.commons.jexl2.parser.ASTGENode;
import org.apache.commons.jexl2.parser.ASTGTNode;
import org.apache.commons.jexl2.parser.ASTJexlScript;
import org.apache.commons.jexl2.parser.ASTLENode;
import org.apache.commons.jexl2.parser.ASTLTNode;
import org.apache.commons.jexl2.parser.ASTNENode;
import org.apache.commons.jexl2.parser.ASTNRNode;
import org.apache.commons.jexl2.parser.ASTNotNode;
import org.apache.commons.jexl2.parser.ASTOrNode;
import org.apache.commons.jexl2.parser.ParseException;
import org.apache.commons.jexl2.parser.ParserTreeConstants;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.google.common.collect.Multimap;

public class BooleanLogicIterator implements SortedKeyValueIterator<Key,Value>, OptionDescriber {
  
  private static final Collection<ByteSequence> EMPTY_COL_FAMS = new ArrayList<ByteSequence>();
  protected static final Logger log = Logger.getLogger(BooleanLogicIterator.class);
  public static final String QUERY_OPTION = "expr";
  public static final String TERM_CARDINALITIES = "TERM_CARDINALITIES"; // comma separated list of term : count
  public static final String FIELD_INDEX_QUERY = "FIELD_INDEX_QUERY";
  public static final String FIELD_NAME_PREFIX = "fi\0";
  // --------------------------------------------------------------------------
  private static IteratorEnvironment env = new DefaultIteratorEnvironment();
  protected Text nullText = new Text();
  private Key topKey = null;
  private Value topValue = null;
  private SortedKeyValueIterator<Key,Value> sourceIterator;
  private BooleanLogicTreeNode root;
  private PriorityQueue<BooleanLogicTreeNode> positives;
  private ArrayList<BooleanLogicTreeNode> negatives = new ArrayList<BooleanLogicTreeNode>();
  private ArrayList<BooleanLogicTreeNode> rangerators;
  private String updatedQuery;
  private Map<String,Long> termCardinalities = new HashMap<String,Long>();
  private Range overallRange = null;
  private FieldIndexKeyParser keyParser;
  
  public BooleanLogicIterator() {
    keyParser = new FieldIndexKeyParser();
    rangerators = new ArrayList<BooleanLogicTreeNode>();
  }
  
  public BooleanLogicIterator(BooleanLogicIterator other, IteratorEnvironment env) {
    if (other.sourceIterator != null) {
      this.sourceIterator = other.sourceIterator.deepCopy(env);
    }
    keyParser = new FieldIndexKeyParser();
    rangerators = new ArrayList<BooleanLogicTreeNode>();
    log.debug("Congratulations, you've reached the BooleanLogicIterator");
  }
  
  public static void setLogLevel(Level lev) {
    log.setLevel(lev);
  }
  
  public void setDebug(Level lev) {
    log.setLevel(lev);
  }
  
  public SortedKeyValueIterator<Key,Value> deepCopy(IteratorEnvironment env) {
    return new BooleanLogicIterator(this, env);
  }
  
  /**
   * <b>init</b> is responsible for setting up the iterator. It will pull the serialized boolean parse tree from the options mapping and construct the
   * appropriate sub-iterators
   * 
   * Once initialized, this iterator will automatically seek to the first matching instance. If no top key exists, that means an event matching the boolean
   * logic did not exist in the partition. Subsequent calls to next will move the iterator and all sub-iterators to the next match.
   * 
   * @param source
   *          The underlying SortedkeyValueIterator.
   * @param options
   *          A Map<String, String> of options.
   * @param env
   *          The iterator environment
   * @throws IOException
   */
  public void init(SortedKeyValueIterator<Key,Value> source, Map<String,String> options, IteratorEnvironment env) throws IOException {
    validateOptions(options);
    try {
      if (log.isDebugEnabled()) {
        log.debug("Congratulations, you've reached the BooleanLogicIterator.init method");
      }
      // Copy the source iterator
      sourceIterator = source.deepCopy(env);
      
      // Potentially take advantage of term cardinalities
      String[] terms = null;
      if (null != options.get(TERM_CARDINALITIES)) {
        terms = options.get(TERM_CARDINALITIES).split(",");
        for (String term : terms) {
          int idx = term.indexOf(":");
          if (-1 != idx) {
            termCardinalities.put(term.substring(0, idx), Long.parseLong(term.substring(idx + 1)));
          }
        }
      }
      
      // Step 1: Parse the query
      if (log.isDebugEnabled()) {
        log.debug("QueryParser");
      }
      QueryParser qp = new QueryParser();
      qp.execute(this.updatedQuery); // validateOptions updates the updatedQuery
      
      // need to build the query tree based on jexl parsing.
      // Step 2: refactor QueryTree - inplace modification
      if (log.isDebugEnabled()) {
        log.debug("transformTreeNode");
      }
      TreeNode tree = qp.getIteratorTree();
      this.root = transformTreeNode(tree);
      
      if (log.isDebugEnabled()) {
        log.debug("refactorTree");
      }
      this.root = refactorTree(this.root);
      
      if (log.isDebugEnabled()) {
        log.debug("collapseBranches");
      }
      collapseBranches(root);
      
      // Step 3: create iterators where we need them.
      createIteratorTree(this.root);
      if (log.isDebugEnabled()) {
        log.debug("Query tree after iterator creation:\n\t" + this.root.getContents());
      }
      // Step 4: split the positive and negative leaves
      splitLeaves(this.root);
      
    } catch (ParseException ex) {
      log.error("ParseException in init: " + ex);
      throw new IllegalArgumentException("Failed to parse query", ex);
    } catch (Exception ex) {
      throw new IllegalArgumentException("probably had no indexed terms", ex);
    }
    
  }
  
  /* *************************************************************************
   * Methods for sub iterator creation.
   */
  private void createIteratorTree(BooleanLogicTreeNode root) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("BoolLogic createIteratorTree()");
    }
    // Walk the tree, if all of your children are leaves, roll you into the
    // appropriate iterator.
    Enumeration<?> dfe = root.depthFirstEnumeration();
    
    while (dfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) dfe.nextElement();
      if (!node.isLeaf() && node.getType() != ParserTreeConstants.JJTJEXLSCRIPT) {
        // try to roll up.
        if (canRollUp(node)) {
          node.setRollUp(true);
          if (node.getType() == ParserTreeConstants.JJTANDNODE) {
            if (log.isDebugEnabled()) {
              log.debug("creating IntersectingIterator");
            }
            node.setUserObject(createIntersectingIterator(node));
          } else if (node.getType() == ParserTreeConstants.JJTORNODE) {
            node.setUserObject(createOrIterator(node));
          } else {
            // throw an error.
            log.debug("createIteratorTree, encounterd a node type I do not know about: " + node.getType());
            log.debug("createIteratorTree, node contents:  " + node.getContents());
          }
          node.removeAllChildren();
        }
      }
    }
    
    // now for remaining leaves, create basic iterators.
    // you can add in specialized iterator mappings here if necessary.
    dfe = root.depthFirstEnumeration();
    while (dfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) dfe.nextElement();
      if (node.isLeaf() && node.getType() != ParserTreeConstants.JJTANDNODE && node.getType() != ParserTreeConstants.JJTORNODE) {
        node.setUserObject(createFieldIndexIterator(node));
      }
    }
  }
  
  private AndIterator createIntersectingIterator(BooleanLogicTreeNode node) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("createIntersectingIterator(node)");
      log.debug("fName: " + node.getFieldName() + " , fValue: " + node.getFieldValue() + " , operator: " + node.getFieldOperator());
    }
    Text[] columnFamilies = new Text[node.getChildCount()];
    Text[] termValues = new Text[node.getChildCount()];
    boolean[] negationMask = new boolean[node.getChildCount()];
    Enumeration<?> children = node.children();
    int i = 0;
    while (children.hasMoreElements()) {
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
      columnFamilies[i] = child.getFieldName();
      termValues[i] = child.getFieldValue();
      negationMask[i] = child.isNegated();
      i++;
    }
    
    AndIterator ii = new AndIterator();
    Map<String,String> options = new HashMap<String,String>();
    options.put(AndIterator.columnFamiliesOptionName, AndIterator.encodeColumns(columnFamilies));
    options.put(AndIterator.termValuesOptionName, AndIterator.encodeTermValues(termValues));
    options.put(AndIterator.notFlagsOptionName, AndIterator.encodeBooleans(negationMask));
    
    ii.init(sourceIterator.deepCopy(env), options, env);
    return ii;
  }
  
  private OrIterator createOrIterator(BooleanLogicTreeNode node) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("createOrIterator(node)");
      log.debug("fName: " + node.getFieldName() + " , fValue: " + node.getFieldValue() + " , operator: " + node.getFieldOperator());
    }
    
    Enumeration<?> children = node.children();
    ArrayList<Text> fams = new ArrayList<Text>();
    ArrayList<Text> quals = new ArrayList<Text>();
    while (children.hasMoreElements()) {
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
      fams.add(child.getFieldName());
      quals.add(child.getFieldValue());
    }
    
    OrIterator iter = new OrIterator();
    SortedKeyValueIterator<Key,Value> source = sourceIterator.deepCopy(env);
    for (int i = 0; i < fams.size(); i++) {
      iter.addTerm(source, fams.get(i), quals.get(i), env);
    }
    
    return iter;
  }
  
  /*
   * This takes the place of the SortedKeyIterator used previously. This iterator is bound to the partitioned table structure. When next is called it will jump
   * rows as necessary internally versus needing to do it externally as was the case with the SortedKeyIterator.
   */
  private FieldIndexIterator createFieldIndexIterator(BooleanLogicTreeNode node) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("BoolLogic.createFieldIndexIterator()");
      log.debug("fName: " + node.getFieldName() + " , fValue: " + node.getFieldValue() + " , operator: " + node.getFieldOperator());
    }
    Text rowId = null;
    sourceIterator.seek(new Range(), EMPTY_COL_FAMS, false);
    if (sourceIterator.hasTop()) {
      rowId = sourceIterator.getTopKey().getRow();
    }
    
    FieldIndexIterator iter = new FieldIndexIterator(node.getType(), rowId, node.getFieldName(), node.getFieldValue(), node.isNegated(),
        node.getFieldOperator());
    
    Map<String,String> options = new HashMap<String,String>();
    iter.init(sourceIterator.deepCopy(env), options, env);
    if (log.isDebugEnabled()) {
      FieldIndexIterator.setLogLevel(Level.DEBUG);
    } else {
      FieldIndexIterator.setLogLevel(Level.OFF);
    }
    
    return iter;
  }
  
  /* *************************************************************************
   * Methods for testing the tree WRT boolean logic.
   */
  // After all iterator pointers have been advanced, test if the current
  // record passes the boolean logic.
  private boolean testTreeState() {
    if (log.isDebugEnabled()) {
      log.debug("BoolLogic testTreeState() begin");
    }
    Enumeration<?> dfe = this.root.depthFirstEnumeration();
    while (dfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) dfe.nextElement();
      if (!node.isLeaf()) {
        
        int type = node.getType();
        if (type == ParserTreeConstants.JJTANDNODE) { // BooleanLogicTreeNode.NodeType.AND) {
          handleAND(node);
        } else if (type == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) {
          handleOR(node);
        } else if (type == ParserTreeConstants.JJTJEXLSCRIPT) {// BooleanLogicTreeNode.NodeType.HEAD) {
          handleHEAD(node);
        } else if (type == ParserTreeConstants.JJTNOTNODE) { // BooleanLogicTreeNode.NodeType.NOT) {
          // there should not be any "NOT"s.
          // throw new Exception();
        }
      } else {
        // it is a leaf, if it is an AND or OR do something
        if (node.getType() == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) { //OrIterator
          node.setValid(node.hasTop());
          node.reSet();
          node.addToSet(node.getTopKey());
          
        } else if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTEQNODE
            || node.getType() == ParserTreeConstants.JJTERNODE || node.getType() == ParserTreeConstants.JJTLENODE
            || node.getType() == ParserTreeConstants.JJTLTNODE || node.getType() == ParserTreeConstants.JJTGENODE
            || node.getType() == ParserTreeConstants.JJTGTNODE) {
          // sub iterator guarantees it is in its internal range,
          // otherwise, no top.
          node.setValid(node.hasTop());
        }
      }
    }
    
    if (log.isDebugEnabled()) {
      log.debug("BoolLogic.testTreeState end, treeState:: " + this.root.getContents() + "  , valid: " + root.isValid());
    }
    return this.root.isValid();
  }
  
  private void handleHEAD(BooleanLogicTreeNode node) {
    Enumeration<?> children = node.children();
    while (children.hasMoreElements()) {
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
      
      if (child.getType() == ParserTreeConstants.JJTANDNODE) {// BooleanLogicTreeNode.NodeType.AND) {
        node.setValid(child.isValid());
        node.setTopKey(child.getTopKey());
      } else if (child.getType() == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) {
        node.setValid(child.isValid());
        node.setTopKey(child.getTopKey());
      } else if (child.getType() == ParserTreeConstants.JJTEQNODE || child.getType() == ParserTreeConstants.JJTERNODE
          || child.getType() == ParserTreeConstants.JJTGTNODE || child.getType() == ParserTreeConstants.JJTGENODE
          || child.getType() == ParserTreeConstants.JJTLTNODE || child.getType() == ParserTreeConstants.JJTLENODE) {// BooleanLogicTreeNode.NodeType.SEL) {
        node.setValid(true);
        node.setTopKey(child.getTopKey());
        if (child.getTopKey() == null) {
          node.setValid(false);
        }
      }
    }// end while
    
    // I have to be valid AND have a top key
    if (node.isValid() && !node.hasTop()) {
      node.setValid(false);
    }
  }
  
  private void handleAND(BooleanLogicTreeNode me) {
    if (log.isDebugEnabled()) {
      log.debug("handleAND::" + me.getContents());
    }
    Enumeration<?> children = me.children();
    me.setValid(true); // it's easier to prove false than true
    
    HashSet<Key> goodSet = new HashSet<Key>();
    HashSet<Key> badSet = new HashSet<Key>();
    while (children.hasMoreElements()) {
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
      
      if (child.getType() == ParserTreeConstants.JJTEQNODE || child.getType() == ParserTreeConstants.JJTANDNODE
          || child.getType() == ParserTreeConstants.JJTERNODE || child.getType() == ParserTreeConstants.JJTNENODE
          || child.getType() == ParserTreeConstants.JJTGENODE || child.getType() == ParserTreeConstants.JJTLENODE
          || child.getType() == ParserTreeConstants.JJTGTNODE || child.getType() == ParserTreeConstants.JJTLTNODE) {
        
        if (child.isNegated()) {
          if (child.hasTop()) {
            badSet.add(child.getTopKey());
            if (goodSet.contains(child.getTopKey())) {
              me.setValid(false);
              return;
            }
            if (child.isValid()) {
              me.setValid(false);
              return;
            }
          }
        } else {
          if (child.hasTop()) {
            if (log.isDebugEnabled()) {
              log.debug("handleAND, child node: " + child.getContents());
            }
            // if you're in the bad set, you're done.
            if (badSet.contains(child.getTopKey())) {
              if (log.isDebugEnabled()) {
                log.debug("handleAND, child is in bad set, setting parent false");
              }
              me.setValid(false);
              return;
            }
            
            // if good set is empty, add it.
            if (goodSet.isEmpty()) {
              if (log.isDebugEnabled()) {
                log.debug("handleAND, goodSet is empty, adding child: " + child.getContents());
              }
              goodSet.add(child.getTopKey());
            } else {
              // must be in the good set & not in the bad set
              // if either fails, I'm false.
              if (!goodSet.contains(child.getTopKey())) {
                if (log.isDebugEnabled()) {
                  log.debug("handleAND, goodSet is not empty, and does NOT contain child, setting false.  child: " + child.getContents());
                }
                me.setValid(false);
                return;
              } else {
                // trim the good set to this one value
                // (handles the case were the initial encounters were ORs)
                goodSet = new HashSet<Key>();
                goodSet.add(child.getTopKey());
                if (log.isDebugEnabled()) {
                  log.debug("handleAND, child in goodset, trim to this value: " + child.getContents());
                }
              }
            }
          } else {
            // test if its children are all false
            if (child.getChildCount() > 0) {
              Enumeration<?> subchildren = child.children();
              boolean allFalse = true;
              while (subchildren.hasMoreElements()) {
                BooleanLogicTreeNode subchild = (BooleanLogicTreeNode) subchildren.nextElement();
                if (!subchild.isNegated()) {
                  allFalse = false;
                  break;
                } else if (subchild.isNegated() && subchild.hasTop()) {
                  allFalse = false;
                  break;
                }
              }
              if (!allFalse) {
                me.setValid(false);
                return;
              }
            } else {
              // child returned a null value and is not a negation, this in turn makes me false.
              me.setValid(false);
              return;
            }
          }
        }
        
      } else if (child.getType() == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) {
      
        // NOTE: The OR may be an OrIterator in which case it will only produce
        // a single unique identifier, or it may be a pure logical construct and
        // be capable of producing multiple unique identifiers.
        // This should handle all cases.
        Iterator<?> iter = child.getSetIterator();
        boolean goodSetEmpty = goodSet.isEmpty();
        boolean matchedOne = false;
        boolean pureNegations = true;
        if (!child.isValid()) {
          if (log.isDebugEnabled()) {
            log.debug("handleAND, child is an OR and it is not valid, setting false, ALL NEGATED?: " + child.isChildrenAllNegated());
          }
          me.setValid(false); // I'm an AND if one of my children is false, I'm false.
          return;
        } else if (child.isValid() && !child.hasTop()) {
          // pure negation, do nothing
        } else if (child.isValid() && child.hasTop()) { // I need to match one
          if (log.isDebugEnabled()) {
            log.debug("handleAND, child OR, valid and has top, means not pureNegations");
          }
          pureNegations = false;
          while (iter.hasNext()) {
            Key i = (Key) iter.next();
            if (child.isNegated()) {
              badSet.add(i);
              if (goodSet.contains(i)) {
                if (log.isDebugEnabled()) {
                  log.debug("handleAND, child OR, goodSet contains bad value: " + i);
                }
                me.setValid(false);
                return;
              }
            } else {
              // if the good set is empty, then push all of my ids.
              if (goodSetEmpty && !badSet.contains(i)) {
                goodSet.add(i);
                matchedOne = true;
              } else {
                // I need at least one to match
                if (goodSet.contains(i)) {
                  matchedOne = true;
                }
              }
            }
          }
        }
        
        // is the goodSet still empty? that means were were only negations
        // otherwise, if it's not empty and we didn't match one, false
        if (child.isNegated()) {
          // we're ok
        } else {
          if (goodSet.isEmpty() && !pureNegations) {
            if (log.isDebugEnabled()) {
              log.debug("handleAND, child OR, empty goodset && !pureNegations, set false");
            }
            // that's bad, we weren't negated, should've pushed something in there.
            me.setValid(false);
            return;
          } else if (!goodSet.isEmpty() && !pureNegations) { // goodSet contains values.
            if (!matchedOne) { // but we didn't match any.
              if (log.isDebugEnabled()) {
                log.debug("handleAND, child OR, goodSet had values but I didn't match any, false");
              }
              me.setValid(false);
              return;
            }
            
            // we matched something, trim the set.
            // i.e. two child ORs
            goodSet = child.getIntersection(goodSet);
          }
        }
        
      }
    }// end while
    
    if (goodSet.isEmpty()) { // && log.isDebugEnabled()) {
      if (log.isDebugEnabled()) {
        log.debug("handleAND-> goodSet is empty, pure negations?");
      }
    } else {
      me.setTopKey(Collections.min(goodSet));
      if (log.isDebugEnabled()) {
        log.debug("End of handleAND, this node's topKey: " + me.getTopKey());
      }
    }
  }
  
  private void handleOR(BooleanLogicTreeNode me) {
    Enumeration<?> children = me.children();
    // I'm an OR node, need at least one positive.
    me.setValid(false);
    me.reSet();
    me.setTopKey(null);
    boolean allNegated = true;
    while (children.hasMoreElements()) {
      // 3 cases for child: SEL, AND, OR
      // and negation
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
      if (child.getType() == ParserTreeConstants.JJTEQNODE || child.getType() == ParserTreeConstants.JJTNENODE
          || child.getType() == ParserTreeConstants.JJTANDNODE || child.getType() == ParserTreeConstants.JJTERNODE
          || child.getType() == ParserTreeConstants.JJTNRNODE || child.getType() == ParserTreeConstants.JJTLENODE
          || child.getType() == ParserTreeConstants.JJTLTNODE || child.getType() == ParserTreeConstants.JJTGENODE
          || child.getType() == ParserTreeConstants.JJTGTNODE) {
        
        if (child.hasTop()) {
          if (child.isNegated()) {
            // do nothing.
          } else {
            allNegated = false;
            // I have something add it to my set.
            if (child.isValid()) {
              me.addToSet(child.getTopKey());
            }
          }
        } else if (!child.isNegated()) { // I have a non-negated child
          allNegated = false;
          // that child could be pure negations in which case I'm true
          me.setValid(child.isValid());
        }
        
      } else if (child.getType() == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) {
        if (child.hasTop()) {
          if (!child.isNegated()) {
            allNegated = false;
            // add its rowIds to my rowIds
            Iterator<?> iter = child.getSetIterator();
            while (iter.hasNext()) {
              Key i = (Key) iter.next();
              if (i != null) {
                me.addToSet(i);
              }
            }
          }
        } else {
          // Or node that doesn't have a top, check if it's valid or not
          // because it could be pure negations itself.
          if (child.isValid()) {
            me.setValid(true);
          }
        }
      }
    }// end while
    
    if (allNegated) {
      // do all my children have top?
      children = me.children();
      while (children.hasMoreElements()) {
        BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
        if (!child.hasTop()) {
          me.setValid(true);
          me.setTopKey(null);
          return;
        }
      }
      me.setValid(false);
      
    } else {
      Key k = me.getMinUniqueID();
      if (k == null) {
        me.setValid(false);
      } else {
        me.setValid(true);
        me.setTopKey(k);
      }
    }
  }
  
  /* *************************************************************************
   * Utility methods.
   */
  // Transforms the TreeNode tree of query.parser into the
  // BooleanLogicTreeNodeJexl form.
  public BooleanLogicTreeNode transformTreeNode(TreeNode node) throws ParseException {
    if (node.getType().equals(ASTEQNode.class) || node.getType().equals(ASTNENode.class)) {
      if (log.isDebugEnabled()) {
        log.debug("Equals Node");
      }
      
      Multimap<String,QueryTerm> terms = node.getTerms();
      for (String fName : terms.keySet()) {
        Collection<QueryTerm> values = terms.get(fName);
        
        for (QueryTerm t : values) {
          if (null == t || null == t.getValue()) {
            continue;
          }
          String fValue = t.getValue().toString();
          fValue = fValue.replaceAll("'", "");
          boolean negated = t.getOperator().equals("!=");
          
          if (!fName.startsWith(FIELD_NAME_PREFIX)) {
            fName = FIELD_NAME_PREFIX + fName;
          }
          BooleanLogicTreeNode child = new BooleanLogicTreeNode(ParserTreeConstants.JJTEQNODE, fName, fValue, negated);
          return child;
        }
      }
    }
    
    if (node.getType().equals(ASTERNode.class) || node.getType().equals(ASTNRNode.class)) {
      if (log.isDebugEnabled()) {
        log.debug("Regex Node");
      }
      
      Multimap<String,QueryTerm> terms = node.getTerms();
      for (String fName : terms.keySet()) {
        Collection<QueryTerm> values = terms.get(fName);
        for (QueryTerm t : values) {
          if (null == t || null == t.getValue()) {
            continue;
          }
          String fValue = t.getValue().toString();
          fValue = fValue.replaceAll("'", "");
          boolean negated = node.getType().equals(ASTNRNode.class);
          
          if (!fName.startsWith(FIELD_NAME_PREFIX)) {
            fName = FIELD_NAME_PREFIX + fName;
          }
          
          BooleanLogicTreeNode child = new BooleanLogicTreeNode(ParserTreeConstants.JJTERNODE, fName, fValue, negated);
          return child;
        }
      }
    }
    
    if (node.getType().equals(ASTLTNode.class) || node.getType().equals(ASTLENode.class) || node.getType().equals(ASTGTNode.class)
        || node.getType().equals(ASTGENode.class)) {
      Multimap<String,QueryTerm> terms = node.getTerms();
      for (String fName : terms.keySet()) {
        Collection<QueryTerm> values = terms.get(fName);
        
        if (!fName.startsWith(FIELD_NAME_PREFIX)) {
          fName = FIELD_NAME_PREFIX + fName;
        }
        for (QueryTerm t : values) {
          if (null == t || null == t.getValue()) {
            continue;
          }
          String fValue = t.getValue().toString();
          fValue = fValue.replaceAll("'", "").toLowerCase();
          boolean negated = false; // to be negated, must be child of Not, which is handled elsewhere.
          int mytype = JexlOperatorConstants.getJJTNodeType(t.getOperator());
          
          BooleanLogicTreeNode child = new BooleanLogicTreeNode(mytype, fName, fValue, negated);
          if (log.isDebugEnabled()) {
            log.debug("adding child node: " + child.getContents());
          }
          return child;
        }
      }
    }
    
    BooleanLogicTreeNode returnNode = null;
    
    if (node.getType().equals(ASTAndNode.class) || node.getType().equals(ASTOrNode.class)) {
      int parentType = node.getType().equals(ASTAndNode.class) ? ParserTreeConstants.JJTANDNODE : ParserTreeConstants.JJTORNODE;
      if (log.isDebugEnabled()) {
        log.debug("AND/OR node: " + parentType);
      }
      if (node.isLeaf() || !node.getTerms().isEmpty()) {
        returnNode = new BooleanLogicTreeNode(parentType);
        Multimap<String,QueryTerm> terms = node.getTerms();
        for (String fName : terms.keySet()) {
          Collection<QueryTerm> values = terms.get(fName);
          if (!fName.startsWith(FIELD_NAME_PREFIX)) {
            fName = FIELD_NAME_PREFIX + fName;
          }
          for (QueryTerm t : values) {
            if (null == t || null == t.getValue()) {
              continue;
            }
            String fValue = t.getValue().toString();
            fValue = fValue.replaceAll("'", "");
            boolean negated = t.getOperator().equals("!=");
            int mytype = JexlOperatorConstants.getJJTNodeType(t.getOperator());
            BooleanLogicTreeNode child = new BooleanLogicTreeNode(mytype, fName, fValue, negated);
            if (log.isDebugEnabled()) {
              log.debug("adding child node: " + child.getContents());
            }
            returnNode.add(child);
          }
        }
      } else {
        returnNode = new BooleanLogicTreeNode(parentType);
        
      }
    } else if (node.getType().equals(ASTNotNode.class)) {
      if (log.isDebugEnabled()) {
        log.debug("NOT node");
      }
      if (node.isLeaf()) {
        // NOTE: this should be cleaned up a bit.
        Multimap<String,QueryTerm> terms = node.getTerms();
        for (String fName : terms.keySet()) {
          Collection<QueryTerm> values = terms.get(fName);
          
          if (!fName.startsWith(FIELD_NAME_PREFIX)) {
            fName = FIELD_NAME_PREFIX + fName;
          }
          for (QueryTerm t : values) {
            if (null == t || null == t.getValue()) {
              continue;
            }
            String fValue = t.getValue().toString();
            fValue = fValue.replaceAll("'", "").toLowerCase();
            boolean negated = !t.getOperator().equals("!=");
            int mytype = JexlOperatorConstants.getJJTNodeType(t.getOperator());
            
            if (!fName.startsWith(FIELD_NAME_PREFIX)) {
              fName = FIELD_NAME_PREFIX + fName;
            }
            return new BooleanLogicTreeNode(mytype, fName, fValue, negated);
          }
        }
      } else {
        returnNode = new BooleanLogicTreeNode(ParserTreeConstants.JJTNOTNODE);
      }
    } else if (node.getType().equals(ASTJexlScript.class) || node.getType().getSimpleName().equals("RootNode")) {
      
      if (log.isDebugEnabled()) {
        log.debug("ROOT/JexlScript node");
      }
      if (node.isLeaf()) {
        returnNode = new BooleanLogicTreeNode(ParserTreeConstants.JJTJEXLSCRIPT);
        // NOTE: this should be cleaned up a bit.
        Multimap<String,QueryTerm> terms = node.getTerms();
        for (String fName : terms.keySet()) {
          Collection<QueryTerm> values = terms.get(fName);
          
          if (!fName.startsWith(FIELD_NAME_PREFIX)) {
            fName = FIELD_NAME_PREFIX + fName;
          }
          for (QueryTerm t : values) {
            if (null == t || null == t.getValue()) {
              continue;
            }
            String fValue = t.getValue().toString();
            fValue = fValue.replaceAll("'", "").toLowerCase();
            boolean negated = t.getOperator().equals("!=");
            int mytype = JexlOperatorConstants.getJJTNodeType(t.getOperator());
            
            BooleanLogicTreeNode child = new BooleanLogicTreeNode(mytype, fName, fValue, negated);
            returnNode.add(child);
            return returnNode;
          }
        }
      } else {
        returnNode = new BooleanLogicTreeNode(ParserTreeConstants.JJTJEXLSCRIPT);
      }
    } else {
      log.error("Currently Unsupported Node type: " + node.getClass().getName() + " \t" + node.getType());
    }
    for (TreeNode child : node.getChildren()) {
      returnNode.add(transformTreeNode(child));
    }
    
    return returnNode;
  }
  
  // After tree conflicts have been resolve, we can collapse branches where
  // leaves have been pruned.
  public static void collapseBranches(BooleanLogicTreeNode myroot) throws Exception {
    
    // NOTE: doing a depth first enumeration didn't wory when I started
    // removing nodes halfway through. The following method does work,
    // it's essentially a reverse breadth first traversal.
    List<BooleanLogicTreeNode> nodes = new ArrayList<BooleanLogicTreeNode>();
    Enumeration<?> bfe = myroot.breadthFirstEnumeration();
    
    while (bfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) bfe.nextElement();
      nodes.add(node);
    }
    
    // walk backwards
    for (int i = nodes.size() - 1; i >= 0; i--) {
      BooleanLogicTreeNode node = nodes.get(i);
      if (log.isDebugEnabled()) {
        log.debug("collapseBranches, inspecting node: " + node.toString() + "  " + node.printNode());
      }
      
      if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTORNODE) {
        if (node.getChildCount() == 0 && !node.isRangeNode()) {
          node.removeFromParent();
        } else if (node.getChildCount() == 1) {
          BooleanLogicTreeNode p = (BooleanLogicTreeNode) node.getParent();
          BooleanLogicTreeNode c = (BooleanLogicTreeNode) node.getFirstChild();
          node.removeFromParent();
          p.add(c);
          
        }
      } else if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) {
        if (node.getChildCount() == 0) {
          if (log.isDebugEnabled()) {
            log.debug("collapseBranches, headNode has no children");
          }
          throw new Exception("Head node has no children.");
        }
      }
    }
    
  }
  
  public BooleanLogicTreeNode refactorTree(BooleanLogicTreeNode myroot) {
    List<BooleanLogicTreeNode> nodes = new ArrayList<BooleanLogicTreeNode>();
    Enumeration<?> bfe = myroot.breadthFirstEnumeration();
    
    while (bfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) bfe.nextElement();
      nodes.add(node);
    }
    
    // walk backwards
    for (int i = nodes.size() - 1; i >= 0; i--) {
      BooleanLogicTreeNode node = nodes.get(i);
      if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTORNODE) {
        // 1. check to see if all children are negated
        // 2. check to see if we have to handle ranges.
        
        Map<Text,RangeBounds> ranges = new HashMap<Text,RangeBounds>();
        Enumeration<?> children = node.children();
        boolean allNegated = true;
        while (children.hasMoreElements()) {
          BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
          if (!child.isNegated()) {
            allNegated = false;
            // break;
          }
          
          // currently we are not allowing unbounded ranges, so they must sit under an AND node.
          if (node.getType() == ParserTreeConstants.JJTANDNODE) {
            // check for ranges
            if (child.getType() == JexlOperatorConstants.JJTGTNODE) {
              if (log.isDebugEnabled()) {
                log.debug("refactor: GT " + child.getContents());
              }
              if (ranges.containsKey(child.getFieldName())) {
                RangeBounds rb = ranges.get(child.getFieldName());
                rb.setLower(child.getFieldValue());
              } else {
                RangeBounds rb = new RangeBounds();
                rb.setLower(child.getFieldValue());
                ranges.put(child.getFieldName(), rb);
              }
            } else if (child.getType() == JexlOperatorConstants.JJTGENODE) {
              if (log.isDebugEnabled()) {
                log.debug("refactor: GE " + child.getContents());
              }
              if (ranges.containsKey(child.getFieldName())) {
                RangeBounds rb = ranges.get(child.getFieldName());
                rb.setLower(child.getFieldValue());
              } else {
                RangeBounds rb = new RangeBounds();
                rb.setLower(child.getFieldValue());
                ranges.put(child.getFieldName(), rb);
              }
            } else if (child.getType() == JexlOperatorConstants.JJTLTNODE) {
              if (log.isDebugEnabled()) {
                log.debug("refactor: LT " + child.getContents());
              }
              if (ranges.containsKey(child.getFieldName())) {
                RangeBounds rb = ranges.get(child.getFieldName());
                rb.setUpper(child.getFieldValue());
              } else {
                RangeBounds rb = new RangeBounds();
                rb.setUpper(child.getFieldValue());
                ranges.put(child.getFieldName(), rb);
              }
            } else if (child.getType() == JexlOperatorConstants.JJTLENODE) {
              if (log.isDebugEnabled()) {
                log.debug("refactor: LE " + child.getContents());
              }
              if (ranges.containsKey(child.getFieldName())) {
                RangeBounds rb = ranges.get(child.getFieldName());
                rb.setUpper(child.getFieldValue());
              } else {
                RangeBounds rb = new RangeBounds();
                rb.setUpper(child.getFieldValue());
                ranges.put(child.getFieldName(), rb);
              }
            }
          }
        }
        if (allNegated) {
          node.setChildrenAllNegated(true);
        }
        
        // see if the AND node had a range.
        if (node.getType() == ParserTreeConstants.JJTANDNODE) {
          
          // if(ranges.containsKey(node.getFieldName())){
          if (!ranges.isEmpty()) {
            // we have a range, process it
            if (node.getChildCount() <= 2 && ranges.size() == 1) {
              if (log.isDebugEnabled()) {
                log.debug("AND range 2 children or less");
              }
              // only has a range, modify the node
              node.setType(ParserTreeConstants.JJTORNODE);
              node.removeAllChildren();
              // RangeBounds rb = ranges.get(node.getFieldName());
              
              for (Entry<Text,RangeBounds> entry : ranges.entrySet()) {
                Text fName = entry.getKey();
                RangeBounds rb = entry.getValue();
                node.setFieldName(fName);
                node.setFieldValue(new Text(""));
                node.setLowerBound(rb.getLower());
                node.setUpperBound(rb.getUpper());
                node.setRangeNode(true);
              }
              
              rangerators.add(node);
              
              if (log.isDebugEnabled()) {
                log.debug("refactor: " + node.getContents());
                log.debug("refactor: " + node.getLowerBound() + "  " + node.getUpperBound());
              }
              
            } else {
              if (log.isDebugEnabled()) {
                log.debug("AND range more than 2 children");
              }
              // node has range plus other children, create another node from the range
              // remove lt,le,gt,ge from parent and push in a single node
              
              // removing nodes via enumeration doesn't work, push into a list
              // and walk backwards
              List<BooleanLogicTreeNode> temp = new ArrayList<BooleanLogicTreeNode>();
              Enumeration<?> e = node.children();
              while (e.hasMoreElements()) {
                BooleanLogicTreeNode c = (BooleanLogicTreeNode) e.nextElement();
                temp.add(c);
              }
              
              for (int j = temp.size() - 1; j >= 0; j--) {
                BooleanLogicTreeNode c = temp.get(j);
                if (c.getType() == JexlOperatorConstants.JJTLENODE || c.getType() == JexlOperatorConstants.JJTLTNODE
                    || c.getType() == JexlOperatorConstants.JJTGENODE || c.getType() == JexlOperatorConstants.JJTGTNODE) {
                  c.removeFromParent();
                }
              }
              
              for (Entry<Text,RangeBounds> entry : ranges.entrySet()) {
                Text fName = entry.getKey();
                BooleanLogicTreeNode nchild = new BooleanLogicTreeNode(ParserTreeConstants.JJTORNODE, fName.toString(), "");
                RangeBounds rb = entry.getValue();
                nchild.setFieldValue(new Text(""));
                nchild.setLowerBound(rb.getLower());
                nchild.setUpperBound(rb.getUpper());
                nchild.setRangeNode(true);
                node.add(nchild);
                rangerators.add(nchild);
              }
              
              if (log.isDebugEnabled()) {
                log.debug("refactor: " + node.getContents());
              }
            }
          }
        }
        
      }
    }
    
    return myroot;
    
  }
  
  // If all children are of type SEL, roll this up into an AND or OR node.
  private static boolean canRollUp(BooleanLogicTreeNode parent) {
    if (log.isDebugEnabled()) {
      log.debug("canRollUp: testing " + parent.getContents());
    }
    if (parent.getChildCount() < 1) {
      if (log.isDebugEnabled()) {
        log.debug("canRollUp: child count < 1, return false");
      }
      return false;
    }
    Enumeration<?> e = parent.children();
    while (e.hasMoreElements()) {
      BooleanLogicTreeNode child = (BooleanLogicTreeNode) e.nextElement();
      
      if (child.getType() != ParserTreeConstants.JJTEQNODE) {// BooleanLogicTreeNode.NodeType.SEL) {
        if (log.isDebugEnabled()) {
          log.debug("canRollUp: child.getType -> " + ParserTreeConstants.jjtNodeName[child.getType()] + " int: " + child.getType() + "  return false");
        }
        return false;
      }
      
      if (child.isNegated()) {
        if (log.isDebugEnabled()) {
          log.debug("canRollUp: child.isNegated, return false");
        }
        return false;
      }
      
      if (child.getFieldValue().toString().contains("*")) {
        if (log.isDebugEnabled()) {
          log.debug("canRollUp: child has wildcard: " + child.getFieldValue());
        }
        return false;
      }
    }
    return true;
  }
  
  /**
   * Small utility function to print out the depth-first enumeration of the tree. Specify the root or sub root of the tree you wish to view.
   * 
   * @param root
   *          The root node of the tree or sub-tree.
   */
  public static void showDepthFirstTraversal(BooleanLogicTreeNode root) {
    System.out.println("DepthFirstTraversal");
    Enumeration<?> e = root.depthFirstEnumeration();
    int i = -1;
    while (e.hasMoreElements()) {
      i += 1;
      BooleanLogicTreeNode n = (BooleanLogicTreeNode) e.nextElement();
      System.out.println(i + " : " + n);
    }
  }
  
  public static void showBreadthFirstTraversal(BooleanLogicTreeNode root) {
    System.out.println("BreadthFirstTraversal");
    log.debug("BooleanLogicIterator.showBreadthFirstTraversal()");
    Enumeration<?> e = root.breadthFirstEnumeration();
    int i = -1;
    while (e.hasMoreElements()) {
      i += 1;
      BooleanLogicTreeNode n = (BooleanLogicTreeNode) e.nextElement();
      System.out.println(i + " : " + n);
      log.debug(i + " : " + n);
    }
  }
  
  private void splitLeaves(BooleanLogicTreeNode node) {
    if (log.isDebugEnabled()) {
      log.debug("BoolLogic: splitLeaves()");
    }
    positives = new PriorityQueue<BooleanLogicTreeNode>(10, new BooleanLogicTreeNodeComparator());
    // positives = new ArrayList<BooleanLogicTreeNodeJexl>();
    negatives.clear();
    
    Enumeration<?> dfe = node.depthFirstEnumeration();
    while (dfe.hasMoreElements()) {
      BooleanLogicTreeNode elem = (BooleanLogicTreeNode) dfe.nextElement();
      
      if (elem.isLeaf()) {
        if (elem.isNegated()) {
          negatives.add(elem);
        } else {
          positives.add(elem);
        }
      }
    }
  }
  
  private void reHeapPriorityQueue(BooleanLogicTreeNode node) {
    positives.clear();
    Enumeration<?> dfe = node.depthFirstEnumeration();
    BooleanLogicTreeNode elem;
    while (dfe.hasMoreElements()) {
      elem = (BooleanLogicTreeNode) dfe.nextElement();
      if (elem.isLeaf() && !elem.isNegated()) {
        positives.add(elem);
      }
    }
  }

  /* *************************************************************************
   * The iterator interface methods.
   */
  public boolean hasTop() {
    return (topKey != null);
  }
  
  public Key getTopKey() {
    if (log.isDebugEnabled()) {
      log.debug("getTopKey: " + topKey);
    }
    return topKey;
  }
  
  private void setTopKey(Key key) {
    if (this.overallRange != null && key != null) {
      if (overallRange.getEndKey() != null) { // if null end key, that means range is to the end of the tablet.
        if (!this.overallRange.contains(key)) {
          topKey = null;
          return;
        }
      }
    }
    topKey = key;
  }
  
  public Value getTopValue() {
    if (topValue == null) {
      topValue = new Value(new byte[0]);
    }
    return topValue;
  }
  
  private void resetNegatives() {
    for (BooleanLogicTreeNode neg : negatives) {
      neg.setTopKey(null);
      neg.setValid(true);
    }
  }
  
  private String getEventKeyUid(Key k) {
    if (k == null || k.getColumnFamily() == null) {
      return null;
    } else {
      return k.getColumnFamily().toString();
    }
  }
  
  private String getIndexKeyUid(Key k) {
    try {
      int idx = 0;
      String sKey = k.getColumnQualifier().toString();
      idx = sKey.indexOf("\0");
      return sKey.substring(idx + 1);
    } catch (Exception e) {
      return null;
    }
  }
  
  /*
   * Remember, the Key in the BooleanLogicTreeNode is different structurally than the Key in its sub iterator because the key BooleanLogic needs to return is an
   * event key created from the index key (which is what the sub iterators are looking at!)
   */
  private Key getOptimizedAdvanceKey() throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("getOptimizedAdvanceKey() called");
    }
    Enumeration<?> bfe = root.breadthFirstEnumeration();
    ArrayList<BooleanLogicTreeNode> bfl = new ArrayList<BooleanLogicTreeNode>();
    while (bfe.hasMoreElements()) {
      BooleanLogicTreeNode node = (BooleanLogicTreeNode) bfe.nextElement();
      if (!node.isNegated()) {
        node.setAdvanceKey(node.getTopKey());
        node.setDone(false);
        bfl.add(node);
      }
    }
    
    // walk the tree backwards
    for (int i = bfl.size() - 1; i >= 0; i--) {
      if (bfl.get(i).isLeaf() || bfl.get(i).isNegated()) {
        if (log.isDebugEnabled()) {
          log.debug("leaf, isDone?: " + bfl.get(i).isDone());
        }
        continue;
      }
      
      BooleanLogicTreeNode node = bfl.get(i);
      node.setDone(false);
      if (log.isDebugEnabled()) {
        log.debug("for loop, node: " + node + " isDone? " + node.isDone());
      }
      if (node.getType() == ParserTreeConstants.JJTANDNODE) {
        // get max
        BooleanLogicTreeNode max = null;
        Enumeration<?> children = node.children();
        boolean firstTime = true;
        while (children.hasMoreElements()) {
          BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
          
          if (child.isNegated() || child.isChildrenAllNegated()) {
            continue;
          }
          
          // all advance keys were initially set from topkey for the leaves.
          if (child.getAdvanceKey() == null) {
            log.debug("\tchild does not advance key: " + child.printNode());
            // i'm an and, i have a child that's done, mark me as done.
            node.setDone(true);
            break;
          } else {
            log.debug("\tchild advanceKey: " + child.getAdvanceKey());
          }
          
          if (firstTime) {
            firstTime = false;
            max = child;
            if (log.isDebugEnabled()) {
              log.debug("\tAND block, first valid child: " + child);
            }
            continue;
          }
          
          log.debug("\tAND block, max: " + max);
          log.debug("\tAND block, child: " + child);
          
          // first test row
          if (max.getAdvanceKey().getRow().compareTo(child.getAdvanceKey().getRow()) < 0) {
            max = child;
            if (log.isDebugEnabled()) {
              log.debug("\tAND block, child row greater, new max.");
            }
            continue;
          }
          
          // if rows are equal, test uids
          String uid_max = getEventKeyUid(max.getAdvanceKey());
          String uid_child = getEventKeyUid(child.getAdvanceKey());
          if (log.isDebugEnabled()) {
            if (uid_max == null) {
              log.debug("\tuid_max is currently null");
            } else {
              log.debug("\tuid_max: " + uid_max);
            }
            if (uid_child == null) {
              log.debug("\tuid_child is null");
            } else {
              log.debug("\tuid_child: " + uid_child);
            }
          }
          
          if (uid_max != null && uid_child != null) {
            if (uid_max.compareTo(uid_child) < 0) {
              max = child;
            }
          } else if (uid_child == null) { // one or the other is null so we want the next row
            max = child;
            log.debug("uid_child is null, we need to grab the next row.");
            break;
          } else {
            log.debug("max is null and child is not, who should we keep? child: " + child);
            break;
          }
        } // end while
        if (log.isDebugEnabled()) {
          log.debug("attemptOptimization: AND with children, max: " + max);
        }
        if (max != null) {
          node.setAdvanceKey(max.getAdvanceKey());
        } else {
          if (log.isDebugEnabled()) {
            log.debug("AND block finished, max is null");
          }
          node.setDone(true);
        }
        
      } else if (node.getType() == ParserTreeConstants.JJTORNODE) {
        // get min
        BooleanLogicTreeNode min = null;
        Enumeration<?> children = node.children();
        boolean firstTime = true;
        int numChildren = node.getChildCount();
        int allChildrenDone = 0;
        
        while (children.hasMoreElements()) {
          BooleanLogicTreeNode child = (BooleanLogicTreeNode) children.nextElement();
          
          if (log.isDebugEnabled()) {
            log.debug("\tOR block start, child: " + child);
          }
          if (child.isNegated() || child.isChildrenAllNegated()) {
            if (log.isDebugEnabled()) {
              log.debug("\tskip negated child: " + child);
            }
            numChildren -= 1;
            continue;
          }
          if (child.isDone()) {
            if (log.isDebugEnabled()) {
              log.debug("\tchild is done: " + child);
            }
            allChildrenDone += 1;
            if (numChildren == allChildrenDone) {
              if (log.isDebugEnabled()) {
                log.debug("\tnumChildren==allChildrenDone, setDone & break");
              }
              // we're done here
              node.setDone(true);
              break;
            }
          }
          
          if (child.getAdvanceKey() == null) {
            log.debug("\tOR child doesn't have top or an AdvanceKey");
            continue;
          }
          if (firstTime) {
            if (log.isDebugEnabled()) {
              log.debug("\tOR block, first valid node, min=child: " + child + "  advanceKey: " + child.getAdvanceKey());
            }
            
            firstTime = false;
            min = child;
            continue;
          }
          if (log.isDebugEnabled()) {
            log.debug("\tOR block, min: " + min);
            log.debug("\tOR block, child: " + child);
          }
          if (min.getAdvanceKey().getRow().toString().compareTo(child.getAdvanceKey().getRow().toString()) > 0) {
            // child row is less than min, set min to child
            min = child;
            if (log.isDebugEnabled()) {
              log.debug("\tmin row was greater than child, min=child: " + min);
            }
            continue;
            
          } else if (min.getAdvanceKey().getRow().compareTo(child.getAdvanceKey().getRow()) < 0) {
            // min row is less child, skip
            if (log.isDebugEnabled()) {
              log.debug("\tmin row less than childs, keep min: " + min);
            }
            continue;
            
          } else { // they're equal, test uids
            String uid_min = getEventKeyUid(min.getAdvanceKey());
            String uid_child = getEventKeyUid(child.getAdvanceKey());
            if (log.isDebugEnabled()) {
              log.debug("\ttesting uids, uid_min: " + uid_min + "  uid_child: " + uid_child);
            }
            if (uid_min != null && uid_child != null) {
              if (uid_min.compareTo(uid_child) > 0) {
                
                min = child;
                if (log.isDebugEnabled()) {
                  log.debug("\tuid_min > uid_child, set min to child: " + min);
                }
              }
            } else if (uid_min == null) {
              if (log.isDebugEnabled()) {
                log.debug("\tuid_min is null, take childs: " + uid_child);
              }
              min = child;
            }
          }
        }// end while
        if (log.isDebugEnabled()) {
          log.debug("attemptOptimization: OR with children, min: " + min);
        }
        
        if (min != null) {
          if (log.isDebugEnabled()) {
            log.debug("OR block, min != null, advanceKey? " + min.getAdvanceKey());
          }
          node.setAdvanceKey(min.getAdvanceKey());
        } else {
          log.debug("OR block, min is null..." + min);
          node.setAdvanceKey(null);
          node.setDone(true);
        }
        
      } else if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) { // HEAD node
        if (log.isDebugEnabled()) {
          log.debug("getOptimizedAdvanceKey, HEAD node");
        }
        BooleanLogicTreeNode child = (BooleanLogicTreeNode) node.getFirstChild();
        
        if (child.isDone()) {
          if (log.isDebugEnabled()) {
            log.debug("Head node's child is done, need to move to the next row");
          }
          Key k = child.getAdvanceKey();
          if (k == null) {
            if (log.isDebugEnabled()) {
              log.debug("HEAD node, advance key is null, try to grab next row from topKey");
            }
            if (hasTop()) {
              k = this.getTopKey();
              child.setAdvanceKey(new Key(new Text(k.getRow().toString() + "\1")));
            } else {
              return null;
            }
          } else {
            Text row = new Text(k.getRow().toString() + "\1");
            k = new Key(row);
            child.setAdvanceKey(k);
          }
          
        }
        if (log.isDebugEnabled()) {
          log.debug("advance Key: " + child.getAdvanceKey());
        }
        Key key = new Key(child.getAdvanceKey().getRow(), child.getAdvanceKey().getColumnFamily(), child.getAdvanceKey().getColumnFamily());
        return key;
        
      }// end else
    }// end for
    return null;
  }
  
  /*
   * The incoming jump key has been formatted into the structure of an index key, but the leaves are eventkeys
   */
  private boolean jump(Key jumpKey) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("JUMP!");
    }
    Enumeration<?> bfe = root.breadthFirstEnumeration();
    while (bfe.hasMoreElements()) {
      BooleanLogicTreeNode n = (BooleanLogicTreeNode) bfe.nextElement();
      n.setAdvanceKey(null);
    } // now advance all nodes to the advance key
    
    if (log.isDebugEnabled()) {
      log.debug("jump, All leaves need to advance to: " + jumpKey);
    }

    String advanceUid = getIndexKeyUid(jumpKey);
    if (log.isDebugEnabled()) {
      log.debug("advanceUid =>  " + advanceUid);
    }
    boolean ok = true;
    for (BooleanLogicTreeNode leaf : positives) {
      leaf.jump(jumpKey);
    }
    return ok;
  }
  
  @SuppressWarnings("unused")
  public void next() throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("next() method called");
    }
    boolean finished = false;
    boolean ok = true;
    if (positives.isEmpty()) {
      setTopKey(null);
      return;
    }
    
    Key previousJumpKey = null;
    while (!finished) {
      
      Key jumpKey = this.getOptimizedAdvanceKey();
      
      if (jumpKey == null) { // stop?
        if (log.isDebugEnabled()) {
          log.debug("next(), jump key is null, stopping");
        }
        setTopKey(null);
        return;
      }
      
      if (log.isDebugEnabled()) {
        if (jumpKey != null) {
          log.debug("next(), jumpKey: " + jumpKey);
        } else {
          log.debug("jumpKey is null");
        }
      }
      
      boolean same = false;
      if (jumpKey != null && topKey != null) {
        // check that the uid's are not the same
        same = getIndexKeyUid(jumpKey).equals(getEventKeyUid(topKey));
        if (log.isDebugEnabled()) {
          log.debug("jumpKeyUid: " + getIndexKeyUid(jumpKey) + "  topKeyUid: " + getEventKeyUid(topKey));
        }
      }
      
      if (log.isDebugEnabled()) {
        log.debug("previousJumpKey: " + previousJumpKey);
        log.debug("current JumpKey: " + jumpKey);
      }
      
      if (jumpKey != null && !this.overallRange.contains(jumpKey)) {
        if (log.isDebugEnabled()) {
          log.debug("jumpKey is outside of range, that means the next key is out of range, stopping");
          log.debug("jumpKey: " + jumpKey + " overallRange.endKey: " + overallRange.getEndKey());
        }
        // stop
        setTopKey(null);
        return;
      }
      
      boolean previousSame = false;
      if (previousJumpKey != null && jumpKey != null) {
        previousSame = previousJumpKey.equals(jumpKey);
      }
      // -----------------------------------
      // OPTIMIZED block
      if (jumpKey != null && !same && !previousSame && ok) {
        previousJumpKey = jumpKey;
        ok = jump(jumpKey); // attempt to jump everybody forward to this row and uid.
        // tryJump = false;
        
        // now test the tree state.
        if (testTreeState()) {
          Key tempKey = root.getTopKey();
          // it is potentially valid, now we need to seek all of the negatives
          if (!negatives.isEmpty()) {
            advanceNegatives(this.root.getTopKey());
            if (!testTreeState()) {
              continue;
            }
          }
          
          if (root.getTopKey().equals(tempKey)) {
            // it's valid set nextKey and make sure it's not the same as topKey.
            if (log.isDebugEnabled()) {
              if (this.root.hasTop()) {
                log.debug("this.root.getTopKey()->" + this.root.getTopKey());
              } else {
                log.debug("next, this.root.getTopKey() is null");
              }
              
              if (topKey != null) {
                log.debug("topKey->" + topKey);
                
              } else {
                log.debug("topKey is null");
              }
            }
            if (compare(topKey, this.root.getTopKey()) != 0) {
              // topKey = this.root.getTopKey();
              setTopKey(this.root.getTopKey());
              return;
            }
          }
        }
        
        // --------------------------------------
        // Regular next block
      } else {
        
        reHeapPriorityQueue(this.root);
        BooleanLogicTreeNode node;

        while (true) {
          node = positives.poll();
          if (!node.isDone() && node.hasTop()) {
            break;
          }
          
          if (positives.isEmpty()) {
            setTopKey(null);
            return;
          }
        }
        
        if (log.isDebugEnabled()) {
          if (jumpKey == null) {
            log.debug("no jump, jumpKey is null");
          } else if (topKey == null) {
            log.debug("no jump, jumpKey: " + jumpKey + "  topKey: null");
          } else {
            log.debug("no jump, jumpKey: " + jumpKey + "  topKey: " + topKey);
          }
          log.debug("next, (no jump) min node: " + node);
          log.debug(node);
        }
        node.next();
        resetNegatives();
        
        if (!node.hasTop()) {
          // it may be part of an or, so it could be ok.
          node.setValid(false);
          if (testTreeState()) {
            // it's valid set nextKey and make sure it's not the same as topKey.
            if (!topKey.equals(this.root.getTopKey())) {
              // topKey = this.root.getTopKey();
              if (this.overallRange != null) {
                if (this.overallRange.contains(root.getTopKey())) {
                  setTopKey(this.root.getTopKey());
                  return;
                } else {
                  setTopKey(null);
                  finished = true;
                  return;
                }
                
              } else {
                setTopKey(this.root.getTopKey());
                return;
              }
            }
          }
        } else {
          
          if (overallRange.contains(node.getTopKey())) {
            // the node had something so push it back into priority queue
            positives.add(node);
          }
          
          // now test the tree state.
          if (testTreeState()) {
            Key tempKey = root.getTopKey();
            // it is potentially valid, now we need to seek all of the negatives
            if (!negatives.isEmpty()) {
              advanceNegatives(this.root.getTopKey());
              if (!testTreeState()) {
                continue;
              }
            }
            
            if (root.getTopKey().equals(tempKey)) {
              // it's valid set nextKey and make sure it's not the same as topKey.
              if (log.isDebugEnabled()) {
                if (this.root.hasTop()) {
                  log.debug("this.root.getTopKey()->" + this.root.getTopKey());
                } else {
                  log.debug("next, this.root.getTopKey() is null");
                }
                
                if (topKey != null) {
                  log.debug("topKey->" + topKey);
                  
                } else {
                  log.debug("topKey is null");
                }
              }
              if (compare(topKey, this.root.getTopKey()) != 0) {
                // topKey = this.root.getTopKey();
                if (this.overallRange != null) {
                  if (overallRange.contains(this.root.getTopKey())) {
                    setTopKey(this.root.getTopKey());
                    return;
                  } else {
                    topKey = null;
                    finished = true;
                    return;
                  }
                } else {
                  setTopKey(this.root.getTopKey());
                  return;
                }
              }
            }
          }
          
        }
        
        // is the priority queue empty?
        if (positives.isEmpty()) {
          finished = true;
          topKey = null;
        }
      }
    }
  }
  
  /*
   * create a range for the given row of the
   */
  private void advanceNegatives(Key k) throws IOException {
    if (log.isDebugEnabled()) {
      log.debug("advancingNegatives for Key: " + k);
    }
    Text rowID = k.getRow();
    Text colFam = k.getColumnFamily();
    
    for (BooleanLogicTreeNode neg : negatives) {
      Key startKey = new Key(rowID, neg.getFieldName(), new Text(neg.getFieldValue() + "\0" + colFam));
      Key endKey = new Key(rowID, neg.getFieldName(), new Text(neg.getFieldValue() + "\0" + colFam + "\1"));
      Range range = new Range(startKey, true, endKey, false);
      
      if (log.isDebugEnabled()) {
        log.debug("range: " + range);
      }
      neg.seek(range, EMPTY_COL_FAMS, false);
      
      if (neg.hasTop()) {
        neg.setValid(false);
      }
      if (log.isDebugEnabled()) {
        if (neg.hasTop()) {
          log.debug("neg top key: " + neg.getTopKey());
        } else {
          log.debug("neg has no top");
        }
      }
    }
  }
  
  public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
    this.overallRange = range;
    if (log.isDebugEnabled()) {
      log.debug("seek, overallRange: " + overallRange);
    }
    // Given some criteria, advance all iterators to that position.
    // NOTE: All of our iterators exist in the leaves.
    topKey = null;
    root.setTopKey(null);
    
    // set up the range iterators for the given seek range.
    // these should exist in the positives as OR iterators, but need special setup.
    setupRangerators(range);
    
    // don't take this out, if you jump rows on the tablet you could have
    // pulled nodes out of the positives priority queue. On a call to seek
    // it is usually jumping rows, so everything needs to become possibly
    // valid again.
    reHeapPriorityQueue(this.root);
    for (BooleanLogicTreeNode node : positives) {
      node.setDone(false);
      node.seek(range, columnFamilies, inclusive);
      if (log.isDebugEnabled()) {
        String tk = "empty";
        if (node.hasTop()) {
          tk = node.getTopKey().toString();
        }
        log.debug("leaf: " + node.getContents() + " topKey: " + tk);
      }
    }
    
    // Now that all nodes have been seek'd recreate the priorityQueue to sort them properly.
    splitLeaves(this.root);
    resetNegatives();
    
    // test Tree, if it's not valid, call next
    if (testTreeState() && overallRange.contains(root.getTopKey())) {
      if (!negatives.isEmpty()) {
        // now advance negatives
        advanceNegatives(this.root.getTopKey());
        if (!testTreeState()) {
          next();
        }
      }
      
      if (log.isDebugEnabled()) {
        log.debug("overallRange " + overallRange + " topKey " + this.root.getTopKey() + " contains " + overallRange.contains(this.root.getTopKey()));
      }

      if (overallRange.contains(this.root.getTopKey()) && this.root.isValid()) {
        setTopKey(this.root.getTopKey());
      } else {
        setTopKey(null);
        return;
      }
    } else {
      // seek failed in the logic test, but there may be other possible
      // values which satisfy the logic tree. Make sure our iterators aren't
      // all null, and then call next.
      
      // if(!root.hasTop()){
      if (log.isDebugEnabled()) {
        log.debug("seek, testTreeState is false, HEAD(root) does not have top");
      }
      // check nodes in positives to see if they're all null/outside range
      // or if nothing percolated up to root yet.
      List<BooleanLogicTreeNode> removals = new ArrayList<BooleanLogicTreeNode>();
      for (BooleanLogicTreeNode node : positives) {
        if (!node.hasTop() || !overallRange.contains(node.getTopKey())) {
          removals.add(node);
        }
      }
      for (BooleanLogicTreeNode node : removals) {
        positives.remove(node);
      }
      next();
      return;
    }
  }
  
  private int compare(Key k1, Key k2) {
    if (k1 != null && k2 != null) {
      return k1.compareTo(k2);
    } else if (k1 == null && k2 == null) {
      return 0;
    } else if (k1 == null) { // in this case, null is considered bigger b/c it's closer to the end of the table.
      return 1;
    } else {
      return -1;
    }
  }
  
  private void setupRangerators(Range range) throws IOException {
    if (rangerators == null || rangerators.isEmpty()) {
      return;
    }
    for (BooleanLogicTreeNode node : rangerators) {
      Set<String> fValues = new HashSet<String>();
      OrIterator orIter = new OrIterator();
      SortedKeyValueIterator<Key,Value> siter = sourceIterator.deepCopy(env);
      // create UniqFieldNameValueIterator to find uniq field names values
      UniqFieldNameValueIterator uniq = new UniqFieldNameValueIterator(node.getFieldName(), node.getLowerBound(), node.getUpperBound());
      uniq.setSource(siter);
      uniq.seek(range, EMPTY_COL_FAMS, false);
      while (uniq.hasTop()) {
        // log.debug("uniq.top: "+uniq.getTopKey());
        Key k = uniq.getTopKey();
        keyParser.parse(k);
        String val = keyParser.getFieldValue();
        if (!fValues.contains(val)) {
          fValues.add(val);
          orIter.addTerm(siter, node.getFieldName(), new Text(val), env);
          if (log.isDebugEnabled()) {
            log.debug("setupRangerators, adding to OR:  " + node.getFieldName() + ":" + val);
          }
        } else {
          log.debug("already have this one: " + val);
        }
        uniq.next();
      }
      node.setUserObject(orIter);
    }
    
  }
  
  /* *************************************************************************
   * Inner classes
   */
  public class BooleanLogicTreeNodeComparator implements Comparator<Object> {
    
    public int compare(Object o1, Object o2) {
      BooleanLogicTreeNode n1 = (BooleanLogicTreeNode) o1;
      BooleanLogicTreeNode n2 = (BooleanLogicTreeNode) o2;
      
      Key k1 = n1.getTopKey();
      Key k2 = n2.getTopKey();
      if (log.isDebugEnabled()) {
        String t1 = "null";
        String t2 = "null";
        if (k1 != null) {
          t1 = k1.getRow().toString() + "\0" + k1.getColumnFamily().toString();
        }
        if (k2 != null) {
          t2 = k2.getRow().toString() + "\0" + k2.getColumnFamily().toString();
        }
        log.debug("BooleanLogicTreeNodeComparator   \tt1: " + t1 + "  t2: " + t2);
      }
      // return t1.compareTo(t2);
      
      if (k1 != null && k2 != null) {
        return k1.compareTo(k2);
      } else if (k1 == null && k2 == null) {
        return 0;
      } else if (k1 == null) {
        return 1;
      } else {
        return -1;
      }
      
    }
  }
  
  public IteratorOptions describeOptions() {
    return new IteratorOptions(getClass().getSimpleName(), "evaluates event objects against an expression", Collections.singletonMap(QUERY_OPTION,
        "query expression"), null);
  }
  
  public boolean validateOptions(Map<String,String> options) {
    if (!options.containsKey(QUERY_OPTION)) {
      return false;
    }
    if (!options.containsKey(FIELD_INDEX_QUERY)) {
      return false;
    }
    this.updatedQuery = options.get(FIELD_INDEX_QUERY);
    return true;
  }
}
