You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ec...@apache.org on 2011/12/27 19:19:44 UTC

svn commit: r1224966 [10/10] - in /incubator/accumulo/branches/1.4: ./ contrib/accumulo_sample/ contrib/accumulo_sample/ingest/src/main/java/aggregator/ contrib/accumulo_sample/ingest/src/main/java/ingest/ contrib/accumulo_sample/ingest/src/test/java/a...

Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/QueryParser.java Tue Dec 27 18:19:43 2011
@@ -90,741 +90,759 @@ import com.google.common.collect.Multima
  *
  */
 public class QueryParser implements ParserVisitor {
-
-	public static class QueryTerm {
-		private boolean negated = false;
-		private String operator = null;
-		private Object value = null;
-		public QueryTerm(boolean negated, String operator,Object value) {
-			super();
-			this.negated = negated;
-			this.operator = operator;
-			this.value = value;
-		}
-		public boolean isNegated() {
-			return negated;
-		}
-		public String getOperator() {
-			return operator;
-		}
-		public Object getValue() {
-			return value;
-		}
-		public void setNegated(boolean negated) {
-			this.negated = negated;
-		}
-		public void setOperator(String operator) {
-			this.operator = operator;
-		}
-		public void setValue(Object value) {
-			this.value = value;
-		}
-		public String toString() {
-			StringBuilder buf = new StringBuilder();
-			buf.append("negated: ").append(negated).append(", operator: ").append(operator).append(", value: ").append(value);
-			return buf.toString();
-		}
-	}
-
-	/**
-	 * Holder object
-	 */
-	static class ObjectHolder {
-		Object object;
-		public Object getObject() {
-			return object;
-		}
-		public void setObject(Object object) {
-			this.object = object;
-		}
-	}
-
-	static class FunctionResult {
-		private List<TermResult> terms = new ArrayList<TermResult>();
-
-		public List<TermResult> getTerms() {
-			return terms;
-		}
-	}
-
-	/**
-	 * Holder object for a term (i.e. field name)
-	 */
-	static class TermResult {
-		Object value;
-		public TermResult(Object value) { this.value = value; }
-	}
-
-	/**
-	 * Holder object for a literal (integer, float, string, or null literal) value
-	 */
-	static class LiteralResult {
-		Object value;
-		public LiteralResult(Object value) { this.value = value; }
-	}
-
-	/**
-	 * Object used to store context information as the AST is being iterated over.
-	 */
-	static class EvaluationContext {
-		boolean inOrContext = false;
-		boolean inNotContext = false;
-		boolean inAndContext = false;
-	}
-
-	/**
-	 * Object to store information from previously parsed queries.
-	 */
-	private static class CacheEntry {
-		private Set<String> negatedTerms = null;
-		private Set<String> andTerms = null;
-		private Set<String> orTerms = null;
-		private Set<Object> literals = null;
-		private Multimap<String,QueryTerm> terms = null;
-		private ASTJexlScript rootNode = null;
-		private TreeNode tree = null;
-		public CacheEntry(Set<String> negatedTerms, Set<String> andTerms,
-				Set<String> orTerms, Set<Object> literals,
-				Multimap<String, QueryTerm> terms, ASTJexlScript rootNode,
-				TreeNode tree) {
-			super();
-			this.negatedTerms = negatedTerms;
-			this.andTerms = andTerms;
-			this.orTerms = orTerms;
-			this.literals = literals;
-			this.terms = terms;
-			this.rootNode = rootNode;
-			this.tree = tree;
-		}
-		public Set<String> getNegatedTerms() {
-			return negatedTerms;
-		}
-		public Set<String> getAndTerms() {
-			return andTerms;
-		}
-		public Set<String> getOrTerms() {
-			return orTerms;
-		}
-		public Set<Object> getLiterals() {
-			return literals;
-		}
-		public Multimap<String, QueryTerm> getTerms() {
-			return terms;
-		}
-		public ASTJexlScript getRootNode() {
-			return rootNode;
-		}
-		public TreeNode getTree() {
-			return tree;
-		}
-	}
-
-	private static final int SEED = 650567;
-
-	private static LRUMap cache = new LRUMap();
-
-	protected Set<String> negatedTerms = new HashSet<String>();
-
-	private Set<String> andTerms = new HashSet<String>();
-
-	private Set<String> orTerms = new HashSet<String>();
-
-	/**
-	 * List of String, Integer, Float, etc literals that were passed in the query
-	 */
-	private Set<Object> literals = new HashSet<Object>();
-	
-	/**
-	 * Map of terms (field names) to QueryTerm objects.
-	 */
-	private Multimap<String,QueryTerm> terms = HashMultimap.create();
-
-	private ASTJexlScript rootNode = null;
-
-	private TreeNode tree = null;
-
-	private int hashVal = 0;
-	
-	public QueryParser() {
-	}
-	
-	private void reset() {
-		this.negatedTerms.clear();
-		this.andTerms.clear();
-		this.orTerms.clear();
-		this.literals.clear();
-		this.terms = HashMultimap.create();
-	}
-
-	public void execute(String query) throws ParseException {
-		reset();
-        query = query.replaceAll("\\s+AND\\s+", " and ");
-        query = query.replaceAll("\\s+OR\\s+", " or ");
-        query = query.replaceAll("\\s+NOT\\s+", " not ");
-
-		//Check to see if its in the cache
-		Hash hash = MurmurHash.getInstance();
-		this.hashVal = hash.hash(query.getBytes(), SEED);
-		if (cache.containsKey(hashVal)) {
-			CacheEntry entry = (CacheEntry) cache.get(hashVal);
-			this.negatedTerms = entry.getNegatedTerms();
-			this.andTerms = entry.getAndTerms();
-			this.orTerms = entry.getOrTerms();
-			this.literals = entry.getLiterals();
-			this.terms = entry.getTerms();
-			this.rootNode = entry.getRootNode();
-			this.tree = entry.getTree();
-		} else {
-			Parser p = new Parser(new StringReader(";"));
-			rootNode = p.parse(new StringReader(query), null);
-			rootNode.childrenAccept(this, null);
-			TreeBuilder builder = new TreeBuilder(rootNode);
-            tree = builder.getRootNode();
-			CacheEntry entry = new CacheEntry(this.negatedTerms, this.andTerms, this.orTerms, this.literals, this.terms, rootNode, tree);
-			cache.put(hashVal, entry);
-		}
-
-	}
-	
-	public static void clearCache() {
-		cache.clear();
-	}
-	
-	/**
-	 *
-	 * @return this queries hash value
-	 */
-	public int getHashValue() {
-		return this.hashVal;
-	}
-
-	public TreeNode getIteratorTree() {
-		return this.tree;
-	}
-
-	/**
-	 *
-	 * @return JEXL abstract syntax tree
-	 */
-	public ASTJexlScript getAST() {
-		return this.rootNode;
-	}
-
-	/**
-	 *
-	 * @return Set of field names to use in the optimizer for nots. As a general
-	 * rule none of these terms should be used to find an event and should they
-	 * should be evaluated on each event after being found.
-	 */
-	public Set<String> getNegatedTermsForOptimizer() {
-		return negatedTerms;
-	}
-
-	/**
-	 *
-	 * @return Set of field names to use in the optimizer for ands. As a general
-	 * rule any one term of an and clause can be used to find associated events.
-	 */
-	public Set<String> getAndTermsForOptimizer() {
-		return andTerms;
-	}
-
-
-	/**
-	 *
-	 * @return Set of field names to use in the optimizer for ors. As a general rule
-	 * any terms that are part of an or clause need to be searched to find the
-	 * associated events.
-	 */
-	public Set<String> getOrTermsForOptimizer() {
-		return orTerms;
-	}
-
-	/**
-	 *
-	 * @return String, Integer, and Float literals used in the query.
-	 */
-	public Set<Object> getQueryLiterals() {
-		return literals;
-	}
-
-	/**
-	 *
-	 * @return Set of all identifiers (field names) in the query.
-	 */
-	public Set<String> getQueryIdentifiers() {
-		return terms.keySet();
-	}
-
-	/**
-	 *
-	 * @return map of term (field name) to QueryTerm object
-	 */
-	public Multimap<String,QueryTerm> getQueryTerms() {
-		return terms;
-	}
-
-	public Object visit(SimpleNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTJexlScript node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTBlock node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTAmbiguous node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTIfStatement node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTWhileStatement node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTForeachStatement node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTAssignment node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTTernaryNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTOrNode node, Object data) {
-		boolean previouslyInOrContext = false;
-		EvaluationContext ctx = null;
-		if (null != data && data instanceof EvaluationContext) {
-			ctx = (EvaluationContext) data;
-			previouslyInOrContext = ctx.inOrContext;
-		} else {
-			ctx = new EvaluationContext();
-		}
-		ctx.inOrContext = true;
-		//Process both sides of this node.
-        node.jjtGetChild(0).jjtAccept(this, ctx);
-        node.jjtGetChild(1).jjtAccept(this, ctx);
-        //reset the state
-        if (null != data && !previouslyInOrContext)
-        	ctx.inOrContext = false;
-		return null;
-	}
-
-	public Object visit(ASTAndNode node, Object data) {
-		boolean previouslyInAndContext = false;
-		EvaluationContext ctx = null;
-		if (null != data && data instanceof EvaluationContext) {
-			ctx = (EvaluationContext) data;
-			previouslyInAndContext = ctx.inAndContext;
-		} else {
-			ctx = new EvaluationContext();
-		}
-		ctx.inAndContext = true;
-		//Process both sides of this node.
-        node.jjtGetChild(0).jjtAccept(this, ctx);
-        node.jjtGetChild(1).jjtAccept(this, ctx);
-        //reset the state
-        if (null != data && !previouslyInAndContext)
-        	ctx.inAndContext = false;
-		return null;
-	}
-
-	public Object visit(ASTBitwiseOrNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTBitwiseXorNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTBitwiseAndNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTEQNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTNENode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = true;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        if (negated)
-        	negatedTerms.add(fieldName.toString());
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTLTNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTGTNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTLENode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTGENode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTERNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTNRNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = true;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        if (negated)
-        	negatedTerms.add(fieldName.toString());
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        terms.put(fieldName.toString(), term);
-		return null;
-	}
-
-	public Object visit(ASTAdditiveNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTAdditiveOperator node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTMulNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTDivNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTModNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTUnaryMinusNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTBitwiseComplNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTNotNode node, Object data) {
-		boolean previouslyInNotContext = false;
-		EvaluationContext ctx = null;
-		if (null != data && data instanceof EvaluationContext) {
-			ctx = (EvaluationContext) data;
-			previouslyInNotContext = ctx.inNotContext;
-		} else {
-			ctx = new EvaluationContext();
-		}
-		ctx.inNotContext = true;
-		//Process both sides of this node.
-        node.jjtGetChild(0).jjtAccept(this, ctx);
-        //reset the state
-        if (null != data && !previouslyInNotContext)
-        	ctx.inNotContext = false;
-		return null;
-	}
-
-	public Object visit(ASTIdentifier node, Object data) {
-		if (data instanceof EvaluationContext) {
-			EvaluationContext ctx = (EvaluationContext) data;
-			if (ctx.inAndContext)
-				andTerms.add(node.image);
-			if (ctx.inNotContext)
-				negatedTerms.add(node.image);
-			if (ctx.inOrContext)
-				orTerms.add(node.image);
-		}
-		return new TermResult(node.image);
-	}
-
-	public Object visit(ASTNullLiteral node, Object data) {
-        literals.add(node.image);
-		return new LiteralResult(node.image);
-	}
-
-	public Object visit(ASTTrueNode node, Object data) {
-		return new LiteralResult(node.image);
-	}
-
-	public Object visit(ASTFalseNode node, Object data) {
-		return new LiteralResult(node.image);
-	}
-
-	public Object visit(ASTIntegerLiteral node, Object data) {
-        literals.add(node.image);
-		return new LiteralResult(node.image);
-	}
-
-	public Object visit(ASTFloatLiteral node, Object data) {
-        literals.add(node.image);
-		return new LiteralResult(node.image);
-	}
-
-	public Object visit(ASTStringLiteral node, Object data) {
-        literals.add("'"+node.image+"'");
-		return new LiteralResult("'"+node.image+"'");
-	}
-
-	public Object visit(ASTArrayLiteral node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTMapLiteral node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTMapEntry node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTEmptyFunction node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTSizeFunction node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTFunctionNode node, Object data) {
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = true;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        //used to rebuild function call from the AST
-        StringBuilder buf = new StringBuilder();
-        String sep = "";
-        // objectNode 0 is the prefix
-        buf.append(node.jjtGetChild(0).image).append(":");
-        // objectNode 1 is the identifier , the others are parameters.
-        buf.append(node.jjtGetChild(1).image).append("(");
-        // process the remaining arguments
-		FunctionResult fr = new FunctionResult();
-        int argc = node.jjtGetNumChildren() - 2;
-        for (int i = 0; i < argc; i++) {
-    		//Process both sides of this node.
-            Object result = node.jjtGetChild(i + 2).jjtAccept(this, data);
-            if (result instanceof TermResult) {
-            	TermResult tr = (TermResult) result;
-            	fr.getTerms().add(tr);
-            	buf.append(sep).append(tr.value);
-            	sep = ", ";            	
-            } else {
-            	buf.append(sep).append(node.jjtGetChild(i + 2).image);
-            	sep = ", ";            	
-            }
-        }
-        buf.append(")");
-        //Capture the entire function call for each function parameter
-        for (TermResult tr : fr.terms)
-        	terms.put((String) tr.value, new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), buf.toString()));
-        return fr;
-	}
-
-	public Object visit(ASTMethodNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTSizeMethod node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTConstructorNode node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTArrayAccess node, Object data) {
-		return null;
-	}
-
-	public Object visit(ASTReference node, Object data) {
-        return node.jjtGetChild(0).jjtAccept(this, data);
-	}
-
-	protected void decodeResults(Object left, Object right, StringBuilder fieldName, ObjectHolder holder) {
-		if (left instanceof TermResult) {
-			TermResult tr = (TermResult) left;
-			fieldName.append((String) tr.value);
-			//Then the right has to be the value
-			if (right instanceof LiteralResult) {
-				holder.setObject(((LiteralResult) right).value);
-			} else {
-				throw new IllegalArgumentException("Object mismatch");
-			}
-		} else if (right instanceof TermResult) {
-			TermResult tr = (TermResult) right;
-			fieldName.append((String) tr.value);
-			if (left instanceof LiteralResult) {
-				holder.setObject(((LiteralResult) left).value);
-			} else {
-				throw new IllegalArgumentException("Object mismatch");
-			}
-
-		} else {
-			throw new IllegalArgumentException("No Term specified in query");
-		}
-	}
+  
+  public static class QueryTerm {
+    private boolean negated = false;
+    private String operator = null;
+    private Object value = null;
+    
+    public QueryTerm(boolean negated, String operator, Object value) {
+      super();
+      this.negated = negated;
+      this.operator = operator;
+      this.value = value;
+    }
+    
+    public boolean isNegated() {
+      return negated;
+    }
+    
+    public String getOperator() {
+      return operator;
+    }
+    
+    public Object getValue() {
+      return value;
+    }
+    
+    public void setNegated(boolean negated) {
+      this.negated = negated;
+    }
+    
+    public void setOperator(String operator) {
+      this.operator = operator;
+    }
+    
+    public void setValue(Object value) {
+      this.value = value;
+    }
+    
+    public String toString() {
+      StringBuilder buf = new StringBuilder();
+      buf.append("negated: ").append(negated).append(", operator: ").append(operator).append(", value: ").append(value);
+      return buf.toString();
+    }
+  }
+  
+  /**
+   * Holder object
+   */
+  static class ObjectHolder {
+    Object object;
+    
+    public Object getObject() {
+      return object;
+    }
+    
+    public void setObject(Object object) {
+      this.object = object;
+    }
+  }
+  
+  static class FunctionResult {
+    private List<TermResult> terms = new ArrayList<TermResult>();
+    
+    public List<TermResult> getTerms() {
+      return terms;
+    }
+  }
+  
+  /**
+   * Holder object for a term (i.e. field name)
+   */
+  static class TermResult {
+    Object value;
+    
+    public TermResult(Object value) {
+      this.value = value;
+    }
+  }
+  
+  /**
+   * Holder object for a literal (integer, float, string, or null literal) value
+   */
+  static class LiteralResult {
+    Object value;
+    
+    public LiteralResult(Object value) {
+      this.value = value;
+    }
+  }
+  
+  /**
+   * Object used to store context information as the AST is being iterated over.
+   */
+  static class EvaluationContext {
+    boolean inOrContext = false;
+    boolean inNotContext = false;
+    boolean inAndContext = false;
+  }
+  
+  /**
+   * Object to store information from previously parsed queries.
+   */
+  private static class CacheEntry {
+    private Set<String> negatedTerms = null;
+    private Set<String> andTerms = null;
+    private Set<String> orTerms = null;
+    private Set<Object> literals = null;
+    private Multimap<String,QueryTerm> terms = null;
+    private ASTJexlScript rootNode = null;
+    private TreeNode tree = null;
+    
+    public CacheEntry(Set<String> negatedTerms, Set<String> andTerms, Set<String> orTerms, Set<Object> literals, Multimap<String,QueryTerm> terms,
+        ASTJexlScript rootNode, TreeNode tree) {
+      super();
+      this.negatedTerms = negatedTerms;
+      this.andTerms = andTerms;
+      this.orTerms = orTerms;
+      this.literals = literals;
+      this.terms = terms;
+      this.rootNode = rootNode;
+      this.tree = tree;
+    }
+    
+    public Set<String> getNegatedTerms() {
+      return negatedTerms;
+    }
+    
+    public Set<String> getAndTerms() {
+      return andTerms;
+    }
+    
+    public Set<String> getOrTerms() {
+      return orTerms;
+    }
+    
+    public Set<Object> getLiterals() {
+      return literals;
+    }
+    
+    public Multimap<String,QueryTerm> getTerms() {
+      return terms;
+    }
+    
+    public ASTJexlScript getRootNode() {
+      return rootNode;
+    }
+    
+    public TreeNode getTree() {
+      return tree;
+    }
+  }
+  
+  private static final int SEED = 650567;
+  
+  private static LRUMap cache = new LRUMap();
+  
+  protected Set<String> negatedTerms = new HashSet<String>();
+  
+  private Set<String> andTerms = new HashSet<String>();
+  
+  private Set<String> orTerms = new HashSet<String>();
+  
+  /**
+   * List of String, Integer, Float, etc literals that were passed in the query
+   */
+  private Set<Object> literals = new HashSet<Object>();
+  
+  /**
+   * Map of terms (field names) to QueryTerm objects.
+   */
+  private Multimap<String,QueryTerm> terms = HashMultimap.create();
+  
+  private ASTJexlScript rootNode = null;
+  
+  private TreeNode tree = null;
+  
+  private int hashVal = 0;
+  
+  public QueryParser() {}
+  
+  private void reset() {
+    this.negatedTerms.clear();
+    this.andTerms.clear();
+    this.orTerms.clear();
+    this.literals.clear();
+    this.terms = HashMultimap.create();
+  }
+  
+  public void execute(String query) throws ParseException {
+    reset();
+    query = query.replaceAll("\\s+AND\\s+", " and ");
+    query = query.replaceAll("\\s+OR\\s+", " or ");
+    query = query.replaceAll("\\s+NOT\\s+", " not ");
+    
+    // Check to see if its in the cache
+    Hash hash = MurmurHash.getInstance();
+    this.hashVal = hash.hash(query.getBytes(), SEED);
+    CacheEntry entry = null;
+    synchronized (cache) {
+      entry = (CacheEntry) cache.get(hashVal);
+    }
+    if (entry != null) {
+      this.negatedTerms = entry.getNegatedTerms();
+      this.andTerms = entry.getAndTerms();
+      this.orTerms = entry.getOrTerms();
+      this.literals = entry.getLiterals();
+      this.terms = entry.getTerms();
+      this.rootNode = entry.getRootNode();
+      this.tree = entry.getTree();
+    } else {
+      Parser p = new Parser(new StringReader(";"));
+      rootNode = p.parse(new StringReader(query), null);
+      rootNode.childrenAccept(this, null);
+      TreeBuilder builder = new TreeBuilder(rootNode);
+      tree = builder.getRootNode();
+      entry = new CacheEntry(this.negatedTerms, this.andTerms, this.orTerms, this.literals, this.terms, rootNode, tree);
+      synchronized (cache) {
+        cache.put(hashVal, entry);
+      }
+    }
+    
+  }
+  
+  /**
+   * 
+   * @return this queries hash value
+   */
+  public int getHashValue() {
+    return this.hashVal;
+  }
+  
+  public TreeNode getIteratorTree() {
+    return this.tree;
+  }
+  
+  /**
+   * 
+   * @return JEXL abstract syntax tree
+   */
+  public ASTJexlScript getAST() {
+    return this.rootNode;
+  }
+  
+  /**
+   * 
+   * @return Set of field names to use in the optimizer for nots. As a general rule none of these terms should be used to find an event and should they should
+   *         be evaluated on each event after being found.
+   */
+  public Set<String> getNegatedTermsForOptimizer() {
+    return negatedTerms;
+  }
+  
+  /**
+   * 
+   * @return Set of field names to use in the optimizer for ands. As a general rule any one term of an and clause can be used to find associated events.
+   */
+  public Set<String> getAndTermsForOptimizer() {
+    return andTerms;
+  }
+  
+  /**
+   * 
+   * @return Set of field names to use in the optimizer for ors. As a general rule any terms that are part of an or clause need to be searched to find the
+   *         associated events.
+   */
+  public Set<String> getOrTermsForOptimizer() {
+    return orTerms;
+  }
+  
+  /**
+   * 
+   * @return String, Integer, and Float literals used in the query.
+   */
+  public Set<Object> getQueryLiterals() {
+    return literals;
+  }
+  
+  /**
+   * 
+   * @return Set of all identifiers (field names) in the query.
+   */
+  public Set<String> getQueryIdentifiers() {
+    return terms.keySet();
+  }
+  
+  /**
+   * 
+   * @return map of term (field name) to QueryTerm object
+   */
+  public Multimap<String,QueryTerm> getQueryTerms() {
+    return terms;
+  }
+  
+  public Object visit(SimpleNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTJexlScript node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTBlock node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTAmbiguous node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTIfStatement node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTWhileStatement node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTForeachStatement node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTAssignment node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTTernaryNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTOrNode node, Object data) {
+    boolean previouslyInOrContext = false;
+    EvaluationContext ctx = null;
+    if (null != data && data instanceof EvaluationContext) {
+      ctx = (EvaluationContext) data;
+      previouslyInOrContext = ctx.inOrContext;
+    } else {
+      ctx = new EvaluationContext();
+    }
+    ctx.inOrContext = true;
+    // Process both sides of this node.
+    node.jjtGetChild(0).jjtAccept(this, ctx);
+    node.jjtGetChild(1).jjtAccept(this, ctx);
+    // reset the state
+    if (null != data && !previouslyInOrContext)
+      ctx.inOrContext = false;
+    return null;
+  }
+  
+  public Object visit(ASTAndNode node, Object data) {
+    boolean previouslyInAndContext = false;
+    EvaluationContext ctx = null;
+    if (null != data && data instanceof EvaluationContext) {
+      ctx = (EvaluationContext) data;
+      previouslyInAndContext = ctx.inAndContext;
+    } else {
+      ctx = new EvaluationContext();
+    }
+    ctx.inAndContext = true;
+    // Process both sides of this node.
+    node.jjtGetChild(0).jjtAccept(this, ctx);
+    node.jjtGetChild(1).jjtAccept(this, ctx);
+    // reset the state
+    if (null != data && !previouslyInAndContext)
+      ctx.inAndContext = false;
+    return null;
+  }
+  
+  public Object visit(ASTBitwiseOrNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTBitwiseXorNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTBitwiseAndNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTEQNode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTNENode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = true;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    if (negated)
+      negatedTerms.add(fieldName.toString());
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTLTNode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTGTNode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTLENode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTGENode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTERNode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = false;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTNRNode node, Object data) {
+    StringBuilder fieldName = new StringBuilder();
+    ObjectHolder value = new ObjectHolder();
+    // Process both sides of this node.
+    Object left = node.jjtGetChild(0).jjtAccept(this, data);
+    Object right = node.jjtGetChild(1).jjtAccept(this, data);
+    // Ignore functions in the query
+    if (left instanceof FunctionResult || right instanceof FunctionResult)
+      return null;
+    decodeResults(left, right, fieldName, value);
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = true;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    if (negated)
+      negatedTerms.add(fieldName.toString());
+    QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
+    terms.put(fieldName.toString(), term);
+    return null;
+  }
+  
+  public Object visit(ASTAdditiveNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTAdditiveOperator node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTMulNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTDivNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTModNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTUnaryMinusNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTBitwiseComplNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTNotNode node, Object data) {
+    boolean previouslyInNotContext = false;
+    EvaluationContext ctx = null;
+    if (null != data && data instanceof EvaluationContext) {
+      ctx = (EvaluationContext) data;
+      previouslyInNotContext = ctx.inNotContext;
+    } else {
+      ctx = new EvaluationContext();
+    }
+    ctx.inNotContext = true;
+    // Process both sides of this node.
+    node.jjtGetChild(0).jjtAccept(this, ctx);
+    // reset the state
+    if (null != data && !previouslyInNotContext)
+      ctx.inNotContext = false;
+    return null;
+  }
+  
+  public Object visit(ASTIdentifier node, Object data) {
+    if (data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inAndContext)
+        andTerms.add(node.image);
+      if (ctx.inNotContext)
+        negatedTerms.add(node.image);
+      if (ctx.inOrContext)
+        orTerms.add(node.image);
+    }
+    return new TermResult(node.image);
+  }
+  
+  public Object visit(ASTNullLiteral node, Object data) {
+    literals.add(node.image);
+    return new LiteralResult(node.image);
+  }
+  
+  public Object visit(ASTTrueNode node, Object data) {
+    return new LiteralResult(node.image);
+  }
+  
+  public Object visit(ASTFalseNode node, Object data) {
+    return new LiteralResult(node.image);
+  }
+  
+  public Object visit(ASTIntegerLiteral node, Object data) {
+    literals.add(node.image);
+    return new LiteralResult(node.image);
+  }
+  
+  public Object visit(ASTFloatLiteral node, Object data) {
+    literals.add(node.image);
+    return new LiteralResult(node.image);
+  }
+  
+  public Object visit(ASTStringLiteral node, Object data) {
+    literals.add("'" + node.image + "'");
+    return new LiteralResult("'" + node.image + "'");
+  }
+  
+  public Object visit(ASTArrayLiteral node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTMapLiteral node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTMapEntry node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTEmptyFunction node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTSizeFunction node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTFunctionNode node, Object data) {
+    // We need to check to see if we are in a NOT context. If so,
+    // then we need to reverse the negation.
+    boolean negated = true;
+    if (null != data && data instanceof EvaluationContext) {
+      EvaluationContext ctx = (EvaluationContext) data;
+      if (ctx.inNotContext)
+        negated = !negated;
+    }
+    // used to rebuild function call from the AST
+    StringBuilder buf = new StringBuilder();
+    String sep = "";
+    // objectNode 0 is the prefix
+    buf.append(node.jjtGetChild(0).image).append(":");
+    // objectNode 1 is the identifier , the others are parameters.
+    buf.append(node.jjtGetChild(1).image).append("(");
+    // process the remaining arguments
+    FunctionResult fr = new FunctionResult();
+    int argc = node.jjtGetNumChildren() - 2;
+    for (int i = 0; i < argc; i++) {
+      // Process both sides of this node.
+      Object result = node.jjtGetChild(i + 2).jjtAccept(this, data);
+      if (result instanceof TermResult) {
+        TermResult tr = (TermResult) result;
+        fr.getTerms().add(tr);
+        buf.append(sep).append(tr.value);
+        sep = ", ";
+      } else {
+        buf.append(sep).append(node.jjtGetChild(i + 2).image);
+        sep = ", ";
+      }
+    }
+    buf.append(")");
+    // Capture the entire function call for each function parameter
+    for (TermResult tr : fr.terms)
+      terms.put((String) tr.value, new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), buf.toString()));
+    return fr;
+  }
+  
+  public Object visit(ASTMethodNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTSizeMethod node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTConstructorNode node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTArrayAccess node, Object data) {
+    return null;
+  }
+  
+  public Object visit(ASTReference node, Object data) {
+    return node.jjtGetChild(0).jjtAccept(this, data);
+  }
+  
+  protected void decodeResults(Object left, Object right, StringBuilder fieldName, ObjectHolder holder) {
+    if (left instanceof TermResult) {
+      TermResult tr = (TermResult) left;
+      fieldName.append((String) tr.value);
+      // Then the right has to be the value
+      if (right instanceof LiteralResult) {
+        holder.setObject(((LiteralResult) right).value);
+      } else {
+        throw new IllegalArgumentException("Object mismatch");
+      }
+    } else if (right instanceof TermResult) {
+      TermResult tr = (TermResult) right;
+      fieldName.append((String) tr.value);
+      if (left instanceof LiteralResult) {
+        holder.setObject(((LiteralResult) left).value);
+      } else {
+        throw new IllegalArgumentException("Object mismatch");
+      }
+      
+    } else {
+      throw new IllegalArgumentException("No Term specified in query");
+    }
+  }
 }

Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/parser/RangeCalculator.java Tue Dec 27 18:19:43 2011
@@ -28,6 +28,13 @@ import java.util.TreeSet;
 import logic.AbstractQueryLogic;
 import normalizer.Normalizer;
 
+import org.apache.accumulo.core.client.BatchScanner;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.TableNotFoundException;
+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.security.Authorizations;
 import org.apache.commons.jexl2.parser.ASTAndNode;
 import org.apache.commons.jexl2.parser.ASTEQNode;
 import org.apache.commons.jexl2.parser.ASTERNode;
@@ -50,13 +57,6 @@ import org.apache.log4j.Logger;
 
 import protobuf.Uid;
 import util.TextUtil;
-import org.apache.accumulo.core.client.BatchScanner;
-import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.TableNotFoundException;
-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.security.Authorizations;
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
@@ -758,66 +758,171 @@ public class RangeCalculator extends Que
         	rightCardinality = 0L;
         TermRange rightRange = ctx.lastRange;
         if (log.isDebugEnabled())
-        	log.debug("[AND-right] term: " + ctx.lastProcessedTerm + ", cardinality: " + rightCardinality + ", ranges: " + rightRange.getRanges().size());
-        
-        //reset the state
-        if (null != data && !previouslyInAndContext)
-        	ctx.inAndContext = false;
-        
-        long card = 0L;
-        TermRange andRange = new TermRange("AND_RESULT", "foo");
-        if ((leftCardinality > 0 && leftCardinality <= rightCardinality) || rightCardinality == 0) {
-        	card = leftCardinality;
-        	andRange.addAll(leftRange.getRanges());
-        } else if ((rightCardinality > 0 && rightCardinality <= leftCardinality) || leftCardinality == 0) {
-        	card = rightCardinality;
-        	andRange.addAll(rightRange.getRanges());
-        } 
-        if (log.isDebugEnabled())
-        	log.debug("[AND] results: " + andRange.getRanges().toString());        
-        ctx.lastRange = andRange;
-        ctx.lastProcessedTerm = "AND_RESULT";
-        this.termCardinalities.put("AND_RESULT", card);
-        
-		return null;
-	}
-
-	@Override
-	public Object visit(ASTEQNode node, Object data) {
-		StringBuilder fieldName = new StringBuilder();
-		ObjectHolder value = new ObjectHolder();
-		//Process both sides of this node.
-        Object left = node.jjtGetChild(0).jjtAccept(this, data);
-        Object right = node.jjtGetChild(1).jjtAccept(this, data);
-        //Ignore functions in the query
-        if (left instanceof FunctionResult || right instanceof FunctionResult)
-        	return null;
-        decodeResults(left, right, fieldName, value);
-        //We need to check to see if we are in a NOT context. If so,
-        //then we need to reverse the negation.
-        boolean negated = false;
-        if (null != data && data instanceof EvaluationContext) {
-        	EvaluationContext ctx = (EvaluationContext) data;
-        	if (ctx.inNotContext)
-        		negated = !negated;
-        }
-        QueryTerm term = new QueryTerm(negated, JexlOperatorConstants.getOperator(node.getClass()), value.getObject());
-        termsCopy.put(fieldName.toString(), term);
-        //Get the terms from the global index
-        //Remove the begin and end ' marks
-        String termValue = null;
-        if (((String) term.getValue()).startsWith("'") && ((String) term.getValue()).endsWith("'"))
-        	termValue = ((String) term.getValue()).substring(1, ((String) term.getValue()).length() - 1);
+          log.debug("Ranges for Global Index query: " + m.toString());
+        this.globalIndexResults.putAll(queryGlobalIndex(m, equals.getKey().getFieldName(), this.indexTableName, false, equals.getKey(), typeFilter));
+      }
+    } catch (TableNotFoundException e) {
+      log.error("index table not found", e);
+      throw new RuntimeException(" index table not found", e);
+    }
+    
+    if (log.isDebugEnabled())
+      log.debug("Ranges from Global Index query: " + globalIndexResults.toString());
+    
+    // Now traverse the AST
+    EvaluationContext ctx = new EvaluationContext();
+    this.getAST().childrenAccept(this, ctx);
+    
+    if (ctx.lastRange.getRanges().size() == 0) {
+      log.debug("No resulting range set");
+    } else {
+      if (log.isDebugEnabled())
+        log.debug("Setting range results to: " + ctx.lastRange.getRanges().toString());
+      this.result = ctx.lastRange.getRanges();
+    }
+  }
+  
+  /**
+   * 
+   * @return set of ranges to use for the shard table
+   */
+  public Set<Range> getResult() {
+    return result;
+  }
+  
+  /**
+   * 
+   * @return map of field names to index field values
+   */
+  public Multimap<String,String> getIndexEntries() {
+    return indexEntries;
+  }
+  
+  public Map<String,String> getIndexValues() {
+    return indexValues;
+  }
+  
+  /**
+   * 
+   * @return Cardinality for each field name.
+   */
+  public Map<String,Long> getTermCardinalities() {
+    return termCardinalities;
+  }
+  
+  /**
+   * 
+   * @param indexRanges
+   * @param tableName
+   * @param isReverse
+   *          switch that determines whether or not to reverse the results
+   * @param override
+   *          mapKey for wildcard and range queries that specify which mapkey to use in the results
+   * @param typeFilter
+   *          - optional list of datatypes
+   * @return
+   * @throws TableNotFoundException
+   */
+  protected Map<MapKey,TermRange> queryGlobalIndex(Map<MapKey,Set<Range>> indexRanges, String specificFieldName, String tableName, boolean isReverse,
+      MapKey override, Set<String> typeFilter) throws TableNotFoundException {
+    
+    // The results map where the key is the field name and field value and the
+    // value is a set of ranges. The mapkey will always be the field name
+    // and field value that was passed in the original query. The TermRange
+    // will contain the field name and field value found in the index.
+    Map<MapKey,TermRange> results = new HashMap<MapKey,TermRange>();
+    
+    // Seed the results map and create the range set for the batch scanner
+    Set<Range> rangeSuperSet = new HashSet<Range>();
+    for (Entry<MapKey,Set<Range>> entry : indexRanges.entrySet()) {
+      rangeSuperSet.addAll(entry.getValue());
+      TermRange tr = new TermRange(entry.getKey().getFieldName(), entry.getKey().getFieldValue());
+      if (null == override)
+        results.put(entry.getKey(), tr);
+      else
+        results.put(override, tr);
+    }
+    
+    if (log.isDebugEnabled())
+      log.debug("Querying global index table: " + tableName + ", range: " + rangeSuperSet.toString() + " colf: " + specificFieldName);
+    BatchScanner bs = this.c.createBatchScanner(tableName, this.auths, this.queryThreads);
+    bs.setRanges(rangeSuperSet);
+    if (null != specificFieldName) {
+      bs.fetchColumnFamily(new Text(specificFieldName));
+    }
+    
+    for (Entry<Key,Value> entry : bs) {
+      if (log.isDebugEnabled()) {
+        log.debug("Index entry: " + entry.getKey().toString());
+      }
+      String fieldValue = null;
+      if (!isReverse) {
+        fieldValue = entry.getKey().getRow().toString();
+      } else {
+        StringBuilder buf = new StringBuilder(entry.getKey().getRow().toString());
+        fieldValue = buf.reverse().toString();
+      }
+      
+      String fieldName = entry.getKey().getColumnFamily().toString();
+      // Get the shard id and datatype from the colq
+      String colq = entry.getKey().getColumnQualifier().toString();
+      int separator = colq.indexOf(EvaluatingIterator.NULL_BYTE_STRING);
+      String shardId = null;
+      String datatype = null;
+      if (separator != -1) {
+        shardId = colq.substring(0, separator);
+        datatype = colq.substring(separator + 1);
+      } else {
+        shardId = colq;
+      }
+      // Skip this entry if the type is not correct
+      if (null != datatype && null != typeFilter && !typeFilter.contains(datatype))
+        continue;
+      // Parse the UID.List object from the value
+      Uid.List uidList = null;
+      try {
+        uidList = Uid.List.parseFrom(entry.getValue().get());
+      } catch (InvalidProtocolBufferException e) {
+        // Don't add UID information, at least we know what shards
+        // it is located in.
+      }
+      
+      // Add the count for this shard to the total count for the term.
+      long count = 0;
+      Long storedCount = termCardinalities.get(fieldName);
+      if (null == storedCount || 0 == storedCount) {
+        count = uidList.getCOUNT();
+      } else {
+        count = uidList.getCOUNT() + storedCount;
+      }
+      termCardinalities.put(fieldName, count);
+      this.indexEntries.put(fieldName, fieldValue);
+      
+      if (null == override)
+        this.indexValues.put(fieldValue, fieldValue);
+      else
+        this.indexValues.put(fieldValue, override.getOriginalQueryValue());
+      
+      // Create the keys
+      Text shard = new Text(shardId);
+      if (uidList.getIGNORE()) {
+        // Then we create a scan range that is the entire shard
+        if (null == override)
+          results.get(new MapKey(fieldName, fieldValue)).add(new Range(shard));
         else
-        	termValue = (String) term.getValue();
-        //Get the values found in the index for this query term
-        TermRange ranges = null;
-        for (MapKey key : this.originalQueryValues.get(termValue)) {
-        	if (key.getFieldName().equalsIgnoreCase(fieldName.toString())) {
-        		ranges = this.globalIndexResults.get(key);
-        		if (log.isDebugEnabled())
-        			log.debug("Results for cached index ranges for key: " + key + " are " + ranges);
-        	}
+          results.get(override).add(new Range(shard));
+      } else {
+        // We should have UUIDs, create event ranges
+        for (String uuid : uidList.getUIDList()) {
+          Text cf = new Text(datatype);
+          TextUtil.textAppend(cf, uuid);
+          Key startKey = new Key(shard, cf);
+          Key endKey = new Key(shard, new Text(cf.toString() + EvaluatingIterator.NULL_BYTE_STRING));
+          Range eventRange = new Range(startKey, true, endKey, false);
+          if (null == override)
+            results.get(new MapKey(fieldName, fieldValue)).add(eventRange);
+          else
+            results.get(override).add(eventRange);
         }
 		//If no result for this field name and value, then add empty range
 		if (null == ranges)

Modified: incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java
URL: http://svn.apache.org/viewvc/incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java?rev=1224966&r1=1224965&r2=1224966&view=diff
==============================================================================
--- incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java (original)
+++ incubator/accumulo/branches/1.4/contrib/accumulo_sample/query/src/main/java/sample/query/Query.java Tue Dec 27 18:19:43 2011
@@ -53,192 +53,195 @@ import org.apache.accumulo.core.client.Z
 @Stateless
 @Local(IQuery.class)
 public class Query implements IQuery {
-	
-	private static final Logger log = Logger.getLogger(Query.class);
-	
-	//Inject values from XML configuration file
-	@Resource(name="instanceName")
-	private String instanceName;
-	
-	@Resource(name="zooKeepers")
-	private String zooKeepers;
-	
-	@Resource(name="username")
-	private String username;
-	
-	@Resource(name="password")
-	private String password;
-	
-	@Resource(name="tableName")
-	private String tableName;
-	
-	@Resource(name="partitions")
-	private int partitions;
-	
-	@Resource(name="threads")
-	private int threads;
-	
-	private static final String XSL = "http://localhost:8080/accumulo-sample/style.xsl";
-			
-	@PostConstruct
-	public void init() {
-		log.info("Post Construct");
-	}
-	
-	@PreDestroy
-	public void close() {
-		log.info("Close called.");
-	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see sample.query.IQuery#html(java.lang.String, java.lang.String)
-	 */
-	public String html(String query, String auths) {
-		log.info("HTML query: " + query);
-		URL u;
-		try {
-			u = new URL(XSL);
-		} catch (MalformedURLException e1) {
-			throw new EJBException("Unable to load XSL stylesheet", e1);
-		}
-		InputStream xslContent;
-		try {
-			xslContent = u.openStream();
-		} catch (IOException e1) {
-			throw new EJBException("Unable to get xsl content", e1);
-		}
-
-		StringWriter xml = new StringWriter();
-		StringWriter html = new StringWriter();
-		
-		Results results = query(query, auths);
-		try {
-			//Marshall the query results object
-			JAXBContext ctx = JAXBContext.newInstance(Results.class);
-			Marshaller m = ctx.createMarshaller();
-			m.marshal(results, xml);
-			
-			//Perform XSL transform on the xml.
-			StringReader reader = new StringReader(xml.toString());
-			TransformerFactory tf = TransformerFactory.newInstance();
-			//Create the transformer from the xsl
-			Templates xsl = tf.newTemplates(new StreamSource(xslContent));
-			Transformer t = xsl.newTransformer();
-			t.transform(new StreamSource(reader), new StreamResult(html));
-			
-		} catch (Exception e) {
-			throw new EJBException("Error processing query results", e);
-		} finally {
-			try {
-				xslContent.close();
-			} catch (IOException e) {
-				throw new EJBException("Unable to close input stream", e);
-			}
-		}
-		return html.toString();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * @see sample.query.IQuery#xml(java.lang.String, java.lang.String)
-	 */
-	public Results xml(String query, String auths) {
-		log.info("XML query: " + query);
-		return query(query, auths);
-	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see sample.query.IQuery#json(java.lang.String, java.lang.String)
-	 */
-	public Results json(String query, String auths) {
-		log.info("JSON query: " + query);
-		return query(query, auths);
-	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see sample.query.IQuery#yaml(java.lang.String, java.lang.String)
-	 */
-	public Results yaml(String query, String auths) {
-		log.info("YAML query: " + query);
-		return query(query, auths);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * @see sample.query.IQuery#content(java.lang.String, java.lang.String)
-	 */
-	public Results content(String query, String auths) {
-		log.info("Content query: " + query);
-		Connector connector = null;
-		if (null == instanceName || null == zooKeepers || null == username || null == password)
-			throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName +
-					", zookeepers = " + this.zooKeepers + ", username = " + this.username +
-					", password = " + this.password +"]. Check values in ejb-jar.xml");
-		Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
-		try {
-			log.info("Connecting to [instanceName = " + this.instanceName +
-					", zookeepers = " + this.zooKeepers + ", username = " + this.username +
-					", password = " + this.password +"].");
-			connector = instance.getConnector(this.username, this.password.getBytes());
-		} catch (Exception e) {
-			throw new EJBException("Error getting connector from instance", e);
-		}
-
-		//Create list of auths
-		List<String> authorizations = new ArrayList<String>();
-		for (String a : auths.split(","))
-			authorizations.add(a);
-		
-		ContentLogic table = new ContentLogic();
-		table.setTableName(tableName);
-		return table.runQuery(connector, query, authorizations);
-
-	}
-
-	/**
-	 * calls the query logic with the parameters, returns results
-	 * 
-	 * @param query
-	 * @param auths
-	 * @return
-	 * @throws ParseException
-	 */
-	public Results query(String query, String auths) {
-
-		Connector connector = null;
-		if (null == instanceName || null == zooKeepers || null == username || null == password)
-			throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName +
-					", zookeepers = " + this.zooKeepers + ", username = " + this.username +
-					", password = " + this.password +"]. Check values in ejb-jar.xml");
-		Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
-		try {
-			log.info("Connecting to [instanceName = " + this.instanceName +
-					", zookeepers = " + this.zooKeepers + ", username = " + this.username +
-					", password = " + this.password +"].");
-			connector = instance.getConnector(this.username, this.password.getBytes());
-		} catch (Exception e) {
-			throw new EJBException("Error getting connector from instance", e);
-		}
-		
-
-		//Create list of auths
-		List<String> authorizations = new ArrayList<String>();
-		for (String a : auths.split(","))
-			authorizations.add(a);
-		
-		QueryLogic table = new QueryLogic();
-		table.setTableName(tableName);
-		table.setMetadataTableName(tableName+"Metadata");
-		table.setIndexTableName(tableName+"Index");
-		table.setReverseIndexTableName(tableName+"ReverseIndex");
-		table.setQueryThreads(threads);
-		table.setUnevaluatedFields("TEXT");
-		table.setNumPartitions(partitions);
-		table.setUseReadAheadIterator(false);
-		return table.runQuery(connector, authorizations, query, null, null, null);
-	}
-	
+  
+  private static final Logger log = Logger.getLogger(Query.class);
+  
+  // Inject values from XML configuration file
+  @Resource(name = "instanceName")
+  private String instanceName;
+  
+  @Resource(name = "zooKeepers")
+  private String zooKeepers;
+  
+  @Resource(name = "username")
+  private String username;
+  
+  @Resource(name = "password")
+  private String password;
+  
+  @Resource(name = "tableName")
+  private String tableName;
+  
+  @Resource(name = "partitions")
+  private int partitions;
+  
+  @Resource(name = "threads")
+  private int threads;
+  
+  private static final String XSL = "/accumulo-sample/style.xsl";
+  
+  @PostConstruct
+  public void init() {
+    log.info("Post Construct");
+  }
+  
+  @PreDestroy
+  public void close() {
+    log.info("Close called.");
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see sample.query.IQuery#html(java.lang.String, java.lang.String)
+   */
+  public String html(String query, String auths) {
+    log.info("HTML query: " + query);
+    URL u;
+    try {
+      u = new URL("http://" + System.getProperty("jboss.bind.address") + ":" + System.getProperty("jboss.web.http.port") + XSL);
+    } catch (MalformedURLException e1) {
+      throw new EJBException("Unable to load XSL stylesheet", e1);
+    }
+    InputStream xslContent;
+    try {
+      xslContent = u.openStream();
+    } catch (IOException e1) {
+      throw new EJBException("Unable to get xsl content", e1);
+    }
+    
+    StringWriter xml = new StringWriter();
+    StringWriter html = new StringWriter();
+    
+    Results results = query(query, auths);
+    try {
+      // Marshall the query results object
+      JAXBContext ctx = JAXBContext.newInstance(Results.class);
+      Marshaller m = ctx.createMarshaller();
+      m.marshal(results, xml);
+      
+      // Perform XSL transform on the xml.
+      StringReader reader = new StringReader(xml.toString());
+      TransformerFactory tf = TransformerFactory.newInstance();
+      // Create the transformer from the xsl
+      Templates xsl = tf.newTemplates(new StreamSource(xslContent));
+      Transformer t = xsl.newTransformer();
+      t.transform(new StreamSource(reader), new StreamResult(html));
+      
+    } catch (Exception e) {
+      throw new EJBException("Error processing query results", e);
+    } finally {
+      try {
+        xslContent.close();
+      } catch (IOException e) {
+        throw new EJBException("Unable to close input stream", e);
+      }
+    }
+    return html.toString();
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see sample.query.IQuery#xml(java.lang.String, java.lang.String)
+   */
+  public Results xml(String query, String auths) {
+    log.info("XML query: " + query);
+    return query(query, auths);
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see sample.query.IQuery#json(java.lang.String, java.lang.String)
+   */
+  public Results json(String query, String auths) {
+    log.info("JSON query: " + query);
+    return query(query, auths);
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see sample.query.IQuery#yaml(java.lang.String, java.lang.String)
+   */
+  public Results yaml(String query, String auths) {
+    log.info("YAML query: " + query);
+    return query(query, auths);
+  }
+  
+  /*
+   * (non-Javadoc)
+   * 
+   * @see sample.query.IQuery#content(java.lang.String, java.lang.String)
+   */
+  public Results content(String query, String auths) {
+    log.info("Content query: " + query);
+    Connector connector = null;
+    if (null == instanceName || null == zooKeepers || null == username || null == password)
+      throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = "
+          + this.username + ", password = " + this.password + "]. Check values in ejb-jar.xml");
+    Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
+    try {
+      log.info("Connecting to [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = " + this.username + ", password = "
+          + this.password + "].");
+      connector = instance.getConnector(this.username, this.password.getBytes());
+    } catch (Exception e) {
+      throw new EJBException("Error getting connector from instance", e);
+    }
+    
+    // Create list of auths
+    List<String> authorizations = new ArrayList<String>();
+    if (auths == null || "".equals(auths)) {
+      authorizations.add("all");
+    } else {
+      for (String a : auths.split(","))
+        authorizations.add(a);
+    }
+    ContentLogic table = new ContentLogic();
+    table.setTableName(tableName);
+    return table.runQuery(connector, query, authorizations);
+    
+  }
+  
+  /**
+   * calls the query logic with the parameters, returns results
+   * 
+   * @param query
+   * @param auths
+   * @return
+   * @throws ParseException
+   */
+  public Results query(String query, String auths) {
+    
+    Connector connector = null;
+    if (null == instanceName || null == zooKeepers || null == username || null == password)
+      throw new EJBException("Required parameters not set. [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = "
+          + this.username + ", password = " + this.password + "]. Check values in ejb-jar.xml");
+    Instance instance = new ZooKeeperInstance(this.instanceName, this.zooKeepers);
+    try {
+      log.info("Connecting to [instanceName = " + this.instanceName + ", zookeepers = " + this.zooKeepers + ", username = " + this.username + ", password = "
+          + this.password + "].");
+      connector = instance.getConnector(this.username, this.password.getBytes());
+    } catch (Exception e) {
+      throw new EJBException("Error getting connector from instance", e);
+    }
+    
+    // Create list of auths
+    List<String> authorizations = new ArrayList<String>();
+    for (String a : auths.split(","))
+      authorizations.add(a);
+    
+    QueryLogic table = new QueryLogic();
+    table.setTableName(tableName);
+    table.setMetadataTableName(tableName + "Metadata");
+    table.setIndexTableName(tableName + "Index");
+    table.setReverseIndexTableName(tableName + "ReverseIndex");
+    table.setQueryThreads(threads);
+    table.setUnevaluatedFields("TEXT");
+    table.setNumPartitions(partitions);
+    table.setUseReadAheadIterator(false);
+    return table.runQuery(connector, authorizations, query, null, null, null);
+  }
+  
 }