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 2013/11/26 16:47:55 UTC
[06/39] ACCUMULO-600 removed wikisearch from trunk
http://git-wip-us.apache.org/repos/asf/accumulo/blob/8db62992/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/EventFields.java
----------------------------------------------------------------------
diff --git a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/EventFields.java b/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/EventFields.java
deleted file mode 100644
index bd43088..0000000
--- a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/EventFields.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * 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.parser;
-
-import java.nio.ByteBuffer;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.apache.accumulo.core.security.ColumnVisibility;
-import org.apache.accumulo.examples.wikisearch.parser.EventFields.FieldValue;
-
-import com.esotericsoftware.kryo.CustomSerialization;
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.serialize.ArraySerializer;
-import com.esotericsoftware.kryo.serialize.IntSerializer;
-import com.esotericsoftware.kryo.serialize.StringSerializer;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.SetMultimap;
-
-/**
- * Object used to hold the fields in an event. This is a multimap because fields can be repeated.
- */
-public class EventFields implements SetMultimap<String,FieldValue>, CustomSerialization {
-
- private static boolean kryoInitialized = false;
- private static ArraySerializer valueSerializer = null;
-
- private Multimap<String,FieldValue> map = null;
-
- public static class FieldValue {
- ColumnVisibility visibility;
- byte[] value;
-
- public FieldValue(ColumnVisibility visibility, byte[] value) {
- super();
- this.visibility = visibility;
- this.value = value;
- }
-
- public ColumnVisibility getVisibility() {
- return visibility;
- }
-
- public byte[] getValue() {
- return value;
- }
-
- public void setVisibility(ColumnVisibility visibility) {
- this.visibility = visibility;
- }
-
- public void setValue(byte[] value) {
- this.value = value;
- }
-
- public int size() {
- return visibility.flatten().length + value.length;
- }
-
- @Override
- public String toString() {
- StringBuilder buf = new StringBuilder();
- if (null != visibility)
- buf.append(" visibility: ").append(new String(visibility.flatten()));
- if (null != value)
- buf.append(" value size: ").append(value.length);
- if (null != value)
- buf.append(" value: ").append(new String(value));
- return buf.toString();
- }
-
- }
-
- public EventFields() {
- map = HashMultimap.create();
- }
-
- public int size() {
- return map.size();
- }
-
- public boolean isEmpty() {
- return map.isEmpty();
- }
-
- public boolean containsKey(Object key) {
- return map.containsKey(key);
- }
-
- public boolean containsValue(Object value) {
- return map.containsValue(value);
- }
-
- public boolean containsEntry(Object key, Object value) {
- return map.containsEntry(key, value);
- }
-
- public boolean put(String key, FieldValue value) {
- return map.put(key, value);
- }
-
- public boolean remove(Object key, Object value) {
- return map.remove(key, value);
- }
-
- public boolean putAll(String key, Iterable<? extends FieldValue> values) {
- return map.putAll(key, values);
- }
-
- public boolean putAll(Multimap<? extends String,? extends FieldValue> multimap) {
- return map.putAll(multimap);
- }
-
- public void clear() {
- map.clear();
- }
-
- public Set<String> keySet() {
- return map.keySet();
- }
-
- public Multiset<String> keys() {
- return map.keys();
- }
-
- public Collection<FieldValue> values() {
- return map.values();
- }
-
- public Set<FieldValue> get(String key) {
- return (Set<FieldValue>) map.get(key);
- }
-
- public Set<FieldValue> removeAll(Object key) {
- return (Set<FieldValue>) map.removeAll(key);
- }
-
- public Set<FieldValue> replaceValues(String key, Iterable<? extends FieldValue> values) {
- return (Set<FieldValue>) map.replaceValues(key, values);
- }
-
- public Set<Entry<String,FieldValue>> entries() {
- return (Set<Entry<String,FieldValue>>) map.entries();
- }
-
- public Map<String,Collection<FieldValue>> asMap() {
- return map.asMap();
- }
-
- public int getByteSize() {
- int count = 0;
- for (Entry<String,FieldValue> e : map.entries()) {
- count += e.getKey().getBytes().length + e.getValue().size();
- }
- return count;
- }
-
- @Override
- public String toString() {
- StringBuilder buf = new StringBuilder();
- for (Entry<String,FieldValue> entry : map.entries()) {
- buf.append("\tkey: ").append(entry.getKey()).append(" -> ").append(entry.getValue().toString()).append("\n");
- }
- return buf.toString();
- }
-
- public static synchronized void initializeKryo(Kryo kryo) {
- if (kryoInitialized)
- return;
- valueSerializer = new ArraySerializer(kryo);
- valueSerializer.setDimensionCount(1);
- valueSerializer.setElementsAreSameType(true);
- valueSerializer.setCanBeNull(false);
- valueSerializer.setElementsCanBeNull(false);
- kryo.register(byte[].class, valueSerializer);
- kryoInitialized = true;
- }
-
- public void readObjectData(Kryo kryo, ByteBuffer buf) {
- if (!kryoInitialized)
- EventFields.initializeKryo(kryo);
- // Read in the number of map entries
- int entries = IntSerializer.get(buf, true);
- for (int i = 0; i < entries; i++) {
- // Read in the key
- String key = StringSerializer.get(buf);
- // Read in the fields in the value
- ColumnVisibility vis = new ColumnVisibility(valueSerializer.readObjectData(buf, byte[].class));
- byte[] value = valueSerializer.readObjectData(buf, byte[].class);
- map.put(key, new FieldValue(vis, value));
- }
-
- }
-
- public void writeObjectData(Kryo kryo, ByteBuffer buf) {
- if (!kryoInitialized)
- EventFields.initializeKryo(kryo);
- // Write out the number of entries;
- IntSerializer.put(buf, map.size(), true);
- for (Entry<String,FieldValue> entry : map.entries()) {
- // Write the key
- StringSerializer.put(buf, entry.getKey());
- // Write the fields in the value
- valueSerializer.writeObjectData(buf, entry.getValue().getVisibility().flatten());
- valueSerializer.writeObjectData(buf, entry.getValue().getValue());
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/8db62992/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/FieldIndexQueryReWriter.java
----------------------------------------------------------------------
diff --git a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/FieldIndexQueryReWriter.java b/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/FieldIndexQueryReWriter.java
deleted file mode 100644
index acfb4f4..0000000
--- a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/FieldIndexQueryReWriter.java
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- * 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.parser;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.swing.tree.DefaultMutableTreeNode;
-
-import org.apache.accumulo.examples.wikisearch.parser.QueryParser.QueryTerm;
-import org.apache.accumulo.examples.wikisearch.parser.RangeCalculator.RangeBounds;
-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.HashMultimap;
-import com.google.common.collect.Multimap;
-
-/**
- * The server-side field index queries can only support operations on indexed fields. Additionally, queries that have differing ranges (i.e. one range at the
- * fieldname level and another at the fieldValue level) are not currently supported. This class removes these conflicts from the query as well as sets proper
- * capitalization configurations etc.
- *
- * Once the query has been modified, you can pass it to the BooleanLogicIterator on the server-side via the options map.
- *
- */
-public class FieldIndexQueryReWriter {
-
- protected static final Logger log = Logger.getLogger(FieldIndexQueryReWriter.class);
- public static final String INDEXED_TERMS_LIST = "INDEXED_TERMS_LIST"; // comma separated list of indexed terms.
- public static Set<Integer> rangeNodeSet;
-
- static {
- rangeNodeSet = new HashSet<Integer>();
- rangeNodeSet.add(ParserTreeConstants.JJTLENODE);
- rangeNodeSet.add(ParserTreeConstants.JJTLTNODE);
- rangeNodeSet.add(ParserTreeConstants.JJTGENODE);
- rangeNodeSet.add(ParserTreeConstants.JJTGTNODE);
- rangeNodeSet = Collections.unmodifiableSet(rangeNodeSet);
- }
-
- /*
- * Given a JEXL Query, rewrite it and return it.
- *
- * 1. ParseQuery 2. Transform query 3. Refactor query 4. remove non-indexed terms a. remove any tree conflicts b. collapse any branches 7. add normalized
- * values 8. adjust for case sensitivity 9. add prefix.. but jexl chokes on null byte
- */
- public static void setLogLevel(Level lev) {
- log.setLevel(lev);
- }
-
- /**
- *
- * @param query
- * @param options
- * @return String representation of a given query.
- * @throws ParseException
- * @throws Exception
- */
- public String removeNonIndexedTermsAndInvalidRanges(String query, Map<String,String> options) throws ParseException, Exception {
- Multimap<String,String> indexedTerms = parseIndexedTerms(options);
- RewriterTreeNode node = parseJexlQuery(query);
- if (log.isDebugEnabled()) {
- log.debug("Tree: " + node.getContents());
- }
- node = removeNonIndexedTerms(node, indexedTerms);
- node = removeTreeConflicts(node, indexedTerms);
- node = collapseBranches(node);
- node = removeNegationViolations(node);
-
- if (log.isDebugEnabled()) {
- log.debug("Tree -NonIndexed: " + node.getContents());
- }
- return rebuildQueryFromTree(node);
- }
-
- /**
- *
- * @param query
- * @param options
- * @return String representation of a given query.
- * @throws ParseException
- * @throws Exception
- */
- public String applyNormalizedTerms(String query, Map<String,String> options) throws ParseException, Exception {
- if (log.isDebugEnabled()) {
- log.debug("applyNormalizedTerms, query: " + query);
- }
- Multimap<String,String> normalizedTerms = parseIndexedTerms(options);
- RewriterTreeNode node = parseJexlQuery(query);
- if (log.isDebugEnabled()) {
- log.debug("applyNormalizedTerms, Tree: " + node.getContents());
- }
- node = orNormalizedTerms(node, normalizedTerms);
- if (log.isDebugEnabled()) {
- log.debug("applyNormalizedTerms,Normalized: " + node.getContents());
- }
- return rebuildQueryFromTree(node);
- }
-
- /**
- *
- * @param query
- * @param fNameUpper
- * @param fValueUpper
- * @return String representation of a given query.
- * @throws ParseException
- */
- public String applyCaseSensitivity(String query, boolean fNameUpper, boolean fValueUpper) throws ParseException {
- RewriterTreeNode node = parseJexlQuery(query);
- if (log.isDebugEnabled()) {
- log.debug("Tree: " + node.getContents());
- }
- node = applyCaseSensitivity(node, fNameUpper, fValueUpper);
- if (log.isDebugEnabled()) {
- log.debug("Case: " + node.getContents());
- }
- return rebuildQueryFromTree(node);
- }
-
- private String rebuildQueryFromTree(RewriterTreeNode node) {
- if (node.isLeaf()) {
- String fName = node.getFieldName();
- String fValue = node.getFieldValue();
- String operator = node.getOperator();
- if (node.isNegated()) {
- if (node.getType() == JexlOperatorConstants.JJTEQNODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTNENODE);
- } else if (node.getType() == JexlOperatorConstants.JJTERNODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTNRNODE);
- } else if (node.getType() == JexlOperatorConstants.JJTLTNODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTGENODE);
- } else if (node.getType() == JexlOperatorConstants.JJTLENODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTGTNODE);
- } else if (node.getType() == JexlOperatorConstants.JJTGTNODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTLENODE);
- } else if (node.getType() == JexlOperatorConstants.JJTGENODE) {
- operator = JexlOperatorConstants.getOperator(JexlOperatorConstants.JJTLTNODE);
- }
- }
- return fName + operator + "'" + fValue + "'";
- } else {
- List<String> parts = new ArrayList<String>();
- Enumeration<?> children = node.children();
- while (children.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) children.nextElement();
- parts.add(rebuildQueryFromTree(child));
- }
- if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) {
- return org.apache.commons.lang.StringUtils.join(parts, "");
- }
- String op = " " + JexlOperatorConstants.getOperator(node.getType()) + " ";
- if (log.isDebugEnabled()) {
- log.debug("Operator: " + op);
- }
- String query = org.apache.commons.lang.StringUtils.join(parts, op);
- query = "(" + query + ")";
- return query;
- }
- }
-
- /*
- * Don't use this, Jexl currently chokes on null bytes in the query
- */
- // public String applyFieldNamePrefix(String query, String prefix) throws ParseException {
- // NuwaveTreeNode node = parseJexlQuery(query);
- // if (log.isDebugEnabled()) {
- // log.debug("Tree: " + node.getContents());
- // }
- // node = applyFieldNamePrefix(node, prefix);
- // if (log.isDebugEnabled()) {
- // log.debug("Prefix: " + node.getContents());
- // }
- // return null;
- // }
- private RewriterTreeNode parseJexlQuery(String query) throws ParseException {
- if (log.isDebugEnabled()) {
- log.debug("parseJexlQuery, query: " + query);
- }
- QueryParser parser = new QueryParser();
- parser.execute(query);
- TreeNode tree = parser.getIteratorTree();
- RewriterTreeNode root = transformTreeNode(tree);
- if (log.isDebugEnabled()) {
- log.debug("parseJexlQuery, transformedTree: " + root.getContents());
- }
- root = refactorTree(root);
- if (log.isDebugEnabled()) {
- log.debug("parseJexlQuery, refactorTree: " + root.getContents());
- }
- return root;
- }
-
- /*
- *
- */
- private RewriterTreeNode transformTreeNode(TreeNode node) throws ParseException {
- if (node.getType().equals(ASTEQNode.class) || node.getType().equals(ASTNENode.class)) {
- if (log.isDebugEnabled()) {
- log.debug("transformTreeNode, 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("!=");
- RewriterTreeNode child = new RewriterTreeNode(ParserTreeConstants.JJTEQNODE, fName, fValue, negated);
- return child;
- }
- }
- }
-
- if (node.getType().equals(ASTERNode.class) || node.getType().equals(ASTNRNode.class)) {
- if (log.isDebugEnabled()) {
- log.debug("transformTreeNode, 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);
- RewriterTreeNode child = new RewriterTreeNode(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)) {
- if (log.isDebugEnabled()) {
- log.debug("transformTreeNode, LT/LE/GT/GE 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("'", "").toLowerCase();
- boolean negated = false; // to be negated, must be child of Not, which is handled elsewhere.
- int mytype = JexlOperatorConstants.getJJTNodeType(t.getOperator());
- RewriterTreeNode child = new RewriterTreeNode(mytype, fName, fValue, negated);
- return child;
- }
- }
- }
-
- RewriterTreeNode 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("transformTreeNode, AND/OR node: " + parentType);
- }
- if (node.isLeaf() || !node.getTerms().isEmpty()) {
- returnNode = new RewriterTreeNode(parentType);
- 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("!=");
- int childType = JexlOperatorConstants.getJJTNodeType(t.getOperator());
- RewriterTreeNode child = new RewriterTreeNode(childType, fName, fValue, negated);
- if (log.isDebugEnabled()) {
- log.debug("adding child node: " + child.getContents());
- }
- returnNode.add(child);
- }
- }
- } else {
- returnNode = new RewriterTreeNode(parentType);
- }
- } else if (node.getType().equals(ASTNotNode.class)) {
- if (log.isDebugEnabled()) {
- log.debug("transformTreeNode, 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);
- 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());
- return new RewriterTreeNode(mytype, fName, fValue, negated);
- }
- }
- } else {
- returnNode = new RewriterTreeNode(ParserTreeConstants.JJTNOTNODE);
- }
- } else if (node.getType().equals(ASTJexlScript.class) || node.getType().getSimpleName().equals("RootNode")) {
-
- if (log.isDebugEnabled()) {
- log.debug("transformTreeNode, ROOT/JexlScript node");
- }
- if (node.isLeaf()) {
- returnNode = new RewriterTreeNode(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);
- 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());
- RewriterTreeNode child = new RewriterTreeNode(mytype, fName, fValue, negated);
- returnNode.add(child);
- return returnNode;
- }
- }
- } else {
- returnNode = new RewriterTreeNode(ParserTreeConstants.JJTJEXLSCRIPT);
- }
- } else {
- log.error("transformTreeNode, Currently Unsupported Node type: " + node.getClass().getName() + " \t" + node.getType());
- }
- for (TreeNode child : node.getChildren()) {
- returnNode.add(transformTreeNode(child));
- }
-
- return returnNode;
- }
-
- private RewriterTreeNode removeNonIndexedTerms(RewriterTreeNode root, Multimap<String,String> indexedTerms) throws Exception {
- // public void removeNonIndexedTerms(BooleanLogicTreeNodeJexl myroot, String indexedTerms) throws Exception {
- if (indexedTerms.isEmpty()) {
- throw new Exception("removeNonIndexedTerms, indexed Terms empty");
- }
-
- // NOTE: doing a depth first enumeration didn't work when I started
- // removing nodes halfway through. The following method does work,
- // it's essentially a reverse breadth first traversal.
- List<RewriterTreeNode> nodes = new ArrayList<RewriterTreeNode>();
- Enumeration<?> bfe = root.breadthFirstEnumeration();
-
- while (bfe.hasMoreElements()) {
- RewriterTreeNode node = (RewriterTreeNode) bfe.nextElement();
- nodes.add(node);
- }
-
- // walk backwards
- for (int i = nodes.size() - 1; i >= 0; i--) {
- RewriterTreeNode node = nodes.get(i);
- if (log.isDebugEnabled()) {
- log.debug("removeNonIndexedTerms, analyzing node: " + node.toString() + " " + node.printNode());
- }
- if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTORNODE) {
- // If all of your children are gone, AND/OR has no purpose, remove
- if (node.getChildCount() == 0) {
- node.removeFromParent();
-
- // If AND/OR has only 1 child, attach it to the parent directly.
- } else if (node.getChildCount() == 1) {
- RewriterTreeNode p = (RewriterTreeNode) node.getParent();
- RewriterTreeNode c = (RewriterTreeNode) node.getFirstChild();
- node.removeFromParent();
- p.add(c);
- }
- } else if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) { // Head node
- // If head node has no children, we have nothing to search on.
- if (node.getChildCount() == 0) {
- throw new Exception();
- }
- } else if (rangeNodeSet.contains(node.getType())) { // leave it alone
- // leave ranges untouched, they'll be handled elsewhere.
- continue;
- } else {
- if (log.isDebugEnabled()) {
- log.debug("removeNonIndexedTerms, Testing: " + node.getFieldName() + ":" + node.getFieldValue());
- }
-
- if (!indexedTerms.containsKey(node.getFieldName().toString() + ":" + node.getFieldValue().toString())) {
- if (log.isDebugEnabled()) {
- log.debug(node.getFieldName() + ":" + node.getFieldValue() + " is NOT indexed");
- }
- node.removeFromParent();
- } else {
- if (log.isDebugEnabled()) {
- log.debug(node.getFieldName() + ":" + node.getFieldValue() + " is indexed");
- }
- }
- }
- }
-
- return root;
- }
-
- private RewriterTreeNode orNormalizedTerms(RewriterTreeNode myroot, Multimap<String,String> indexedTerms) throws Exception {
- // we have multimap of FieldName to multiple FieldValues
- if (indexedTerms.isEmpty()) {
- throw new Exception("indexed Terms empty");
- }
- try {
- // NOTE: doing a depth first enumeration didn't work when I started
- // removing nodes halfway through. The following method does work,
- // it's essentially a reverse breadth first traversal.
- List<RewriterTreeNode> nodes = new ArrayList<RewriterTreeNode>();
- Enumeration<?> bfe = myroot.breadthFirstEnumeration();
-
- while (bfe.hasMoreElements()) {
- RewriterTreeNode node = (RewriterTreeNode) bfe.nextElement();
- nodes.add(node);
- }
-
- // walk backwards
- for (int i = nodes.size() - 1; i >= 0; i--) {
- RewriterTreeNode node = nodes.get(i);
- if (log.isDebugEnabled()) {
- log.debug("orNormalizedTerms, analyzing node: " + node.toString() + " " + node.printNode());
- }
- if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTORNODE) {
- continue;
- } else if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) {
- if (node.getChildCount() == 0) {
- if (log.isDebugEnabled()) {
- log.debug("orNormalizedTerms: Head node has no children!");
- }
- throw new Exception(); // Head node has no children.
- }
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Testing data location: " + node.getFieldName());
- }
- String fName = node.getFieldName().toString();
- String fValue = node.getFieldValue().toString();
- if (indexedTerms.containsKey(fName + ":" + fValue)) {
-
- if (indexedTerms.get(fName + ":" + fValue).size() > 1) {
- // Replace node with an OR, and make children from the multimap collection
- node.setType(ParserTreeConstants.JJTORNODE);
- boolean neg = node.isNegated();
- node.setNegated(false);
- node.setFieldName(null);
- node.setFieldValue(null);
- Collection<String> values = indexedTerms.get(fName + ":" + fValue);
- for (String value : values) {
- RewriterTreeNode n = new RewriterTreeNode(ParserTreeConstants.JJTEQNODE, fName, value, neg);
- node.add(n);
- }
- } else if (indexedTerms.get(fName + ":" + fValue).size() == 1) {
- // Straight replace
- Collection<String> values = indexedTerms.get(fName + ":" + fValue);
- for (String val : values) {
- // should only be 1
- node.setFieldValue(val);
- }
- }
-
- } else {
- // throw new Exception("orNormalizedTerms, encountered a non-indexed term: " + node.getFieldName().toString());
- }
- }
- }
- } catch (Exception e) {
- log.debug("Caught exception in orNormalizedTerms(): " + e);
- throw new Exception("exception in: orNormalizedTerms");
- }
-
- return myroot;
- }
-
- /***
- * We only want to pass ranges on if they meet a very narrow set of conditions. All ranges must be bounded i.e. x between(1,5) so their parent is an AND. We
- * will only pass a range if 1. The AND is the direct child of HEAD node 2. The AND is a child of an OR which is a direct child of HEAD node.
- *
- * If there is an HEAD-AND[x,OR[b,AND[range]]], and you remove the range, this turns the tree into HEAD-AND[X,OR[B]] which becomes HEAD-AND[X,B] which will
- * miss entries, so you need to cut out the entire OR at this point and let the positive side of the AND pick it up.
- */
- private RewriterTreeNode removeTreeConflicts(RewriterTreeNode root, Multimap<String,String> indexedTerms) {
- if (log.isDebugEnabled()) {
- log.debug("removeTreeConflicts");
- }
-
- /*
- * You can't modify the enumeration, so save it into a list. We want to walk backwards in a breadthFirstEnumeration. So we don't throw null pointers when we
- * erase nodes and shorten our list.
- */
- List<RewriterTreeNode> nodeList = new ArrayList<RewriterTreeNode>();
- Enumeration<?> nodes = root.breadthFirstEnumeration();
- while (nodes.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) nodes.nextElement();
- nodeList.add(child);
- }
-
- // walk backwards
- for (int i = nodeList.size() - 1; i >= 0; i--) {
- RewriterTreeNode node = nodeList.get(i);
-
- if (node.isRemoval()) {
- node.removeFromParent();
- continue;
- }
-
- RewriterTreeNode parent = (RewriterTreeNode) node.getParent();
- /*
- * All ranges must be bounded! This means the range must be part of an AND, and the parent of AND must be a HEAD node or an OR whose parent is a HEAD
- * node.
- */
- if (node.getType() == ParserTreeConstants.JJTANDNODE
- && (node.getLevel() == 1 || (parent.getType() == ParserTreeConstants.JJTORNODE && parent.getLevel() == 1))) {
-
- if (log.isDebugEnabled()) {
- log.debug("AND at level 1 or with OR parent at level 1");
- }
- Map<Text,RangeBounds> rangeMap = getBoundedRangeMap(node);
-
- // can't modify the enumeration... save children to a list.
- List<RewriterTreeNode> childList = new ArrayList<RewriterTreeNode>();
- Enumeration<?> children = node.children();
- while (children.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) children.nextElement();
- childList.add(child);
- }
-
- for (int j = childList.size() - 1; j >= 0; j--) {
- RewriterTreeNode child = childList.get(j);
- // currently we are not allowing unbounded ranges, so they must sit under an AND node.
- if (rangeNodeSet.contains(child.getType())) {
- if (log.isDebugEnabled()) {
- log.debug("child type: " + JexlOperatorConstants.getOperator(child.getType()));
- }
- if (rangeMap == null) {
- // remove
- child.removeFromParent();
- } else {
- if (!rangeMap.containsKey(new Text(child.getFieldName()))) {
- child.removeFromParent();
- } else {
- // check if it has a single non-range sibling
- boolean singleSib = false;
- if (log.isDebugEnabled()) {
- log.debug("checking for singleSib.");
- }
- Enumeration<?> sibs = child.getParent().children();
- while (sibs.hasMoreElements()) {
- RewriterTreeNode sib = (RewriterTreeNode) sibs.nextElement();
- if (!rangeNodeSet.contains(sib.getType())) {
- singleSib = true;
- break;
- }
- }
- if (singleSib) {
- child.removeFromParent();
- } else {
- if (indexedTerms.containsKey(child.getFieldName() + ":" + child.getFieldValue())) {
- if (log.isDebugEnabled()) {
- log.debug("removeTreeConflicts, node: " + node.getContents());
- }
- // swap parent AND with an OR
- node.removeAllChildren();
- node.setType(ParserTreeConstants.JJTORNODE);
-
- Collection<String> values = indexedTerms.get(child.getFieldName() + ":" + child.getFieldValue());
- for (String value : values) {
- RewriterTreeNode n = new RewriterTreeNode(ParserTreeConstants.JJTEQNODE, child.getFieldName(), value, child.isNegated());
- node.add(n);
- }
- if (log.isDebugEnabled()) {
- log.debug("removeTreeConflicts, node: " + node.getContents());
- }
-
- break;
- } else {
- child.removeFromParent();
- }
-
- }
- }
- }
- }
- }// end inner for
-
- } else { // remove all ranges!
- if (node.isLeaf()) {
- continue;
- }
- // can't modify the enumeration...
- List<RewriterTreeNode> childList = new ArrayList<RewriterTreeNode>();
- Enumeration<?> children = node.children();
- while (children.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) children.nextElement();
- childList.add(child);
- }
-
- // walk backwards
- for (int j = childList.size() - 1; j >= 0; j--) {
-
- RewriterTreeNode child = childList.get(j);
- if (log.isDebugEnabled()) {
- log.debug("removeTreeConflicts, looking at node: " + node);
- }
- if (rangeNodeSet.contains(child.getType())) {
- // if grand parent is an OR and not top level, mark whole thing for removal.
- RewriterTreeNode grandParent = (RewriterTreeNode) child.getParent().getParent();
- if (grandParent.getType() == ParserTreeConstants.JJTORNODE && grandParent.getLevel() != 1) {
- grandParent.setRemoval(true);
- }
- child.removeFromParent();
- }
- }
- }
-
- }// end outer for
-
- return root;
- }
-
- private RewriterTreeNode removeNegationViolations(RewriterTreeNode node) throws Exception {
- // Double check the top level node for negation violations
- // if AND, one child must be positive, if OR, no negatives allowed.
- RewriterTreeNode one = (RewriterTreeNode) node.getFirstChild(); // Head node has only 1 child.
- ArrayList<RewriterTreeNode> childrenList = new ArrayList<RewriterTreeNode>();
- Enumeration<?> children = one.children();
- while (children.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) children.nextElement();
- childrenList.add(child);
- }
- if (one.getType() == JexlOperatorConstants.JJTORNODE) {
- for (RewriterTreeNode child : childrenList) {
- if (child.isNegated()) {
- child.removeFromParent();
- }
- }
- if (one.getChildCount() == 0) {
- throw new Exception("FieldIndexQueryReWriter: Top level query node cannot be processed.");
- }
- } else if (one.getType() == JexlOperatorConstants.JJTANDNODE) {
- boolean ok = false;
- for (RewriterTreeNode child : childrenList) {
- if (!child.isNegated()) {
- ok = true;
- break;
- }
- }
- if (!ok) {
- throw new Exception("FieldIndexQueryReWriter: Top level query node cannot be processed.");
- }
- }
-
- return node;
- }
-
- // After tree conflicts have been resolve, we can collapse branches where
- // leaves have been pruned.
- private RewriterTreeNode collapseBranches(RewriterTreeNode 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<RewriterTreeNode> nodes = new ArrayList<RewriterTreeNode>();
- Enumeration<?> bfe = myroot.breadthFirstEnumeration();
-
- while (bfe.hasMoreElements()) {
- RewriterTreeNode node = (RewriterTreeNode) bfe.nextElement();
- nodes.add(node);
- }
-
- // walk backwards
- for (int i = nodes.size() - 1; i >= 0; i--) {
- RewriterTreeNode 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.removeFromParent();
- } else if (node.getChildCount() == 1) {
- RewriterTreeNode p = (RewriterTreeNode) node.getParent();
- RewriterTreeNode c = (RewriterTreeNode) node.getFirstChild();
- node.removeFromParent();
- p.add(c);
-
- }
- } else if (node.getType() == ParserTreeConstants.JJTJEXLSCRIPT) {
- if (node.getChildCount() == 0) {
- throw new Exception();
- }
- }
- }
- return myroot;
- }
-
- /**
- * @param options
- */
- public Multimap<String,String> parseIndexedTerms(Map<String,String> options) {
- if (options.get(INDEXED_TERMS_LIST) != null) {
- Multimap<String,String> mmap = HashMultimap.create();
- String[] items = options.get(INDEXED_TERMS_LIST).split(";");
- for (String item : items) {
- item = item.trim();
- if (log.isDebugEnabled()) {}
- String[] parts = item.split(":");
- if (log.isDebugEnabled()) {
- log.debug("adding: " + parts[0]);
- }
- for (int i = 2; i < parts.length; i++) {
- // key is original query token, i.e. color:red
- mmap.put(parts[0] + ":" + parts[1], parts[i]);
-
- }
-
- }
- if (log.isDebugEnabled()) {
- log.debug("multimap: " + mmap);
- }
- return mmap;
- }
- if (log.isDebugEnabled()) {
- log.debug("parseIndexedTerms: returning null");
- }
- return null;
- }
-
- /**
- * @param root
- */
- public RewriterTreeNode refactorTree(RewriterTreeNode root) {
- Enumeration<?> dfe = root.breadthFirstEnumeration();
-
- while (dfe.hasMoreElements()) {
- RewriterTreeNode n = (RewriterTreeNode) dfe.nextElement();
-
- if (n.getType() == ParserTreeConstants.JJTNOTNODE) {// BooleanLogicTreeNode.NodeType.NOT) {
- RewriterTreeNode child = (RewriterTreeNode) n.getChildAt(0);
- child.setNegated(true);
- RewriterTreeNode parent = (RewriterTreeNode) n.getParent();
- parent.remove(n);
- parent.add(child);
- }
- }
-
- // cycle through again and distribute nots
- Enumeration<?> bfe = root.breadthFirstEnumeration();
- RewriterTreeNode child;
-
- while (bfe.hasMoreElements()) {
- child = (RewriterTreeNode) bfe.nextElement();
-
- if (child.isNegated()) {
- if (child.getChildCount() > 0) {
- demorganSubTree(child);
-
- }
- }
- }
- return root;
-
- }
-
- private void demorganSubTree(RewriterTreeNode root) {
-
- root.setNegated(false);
- // root.setChildrenAllNegated(true);
-
- if (root.getType() == ParserTreeConstants.JJTANDNODE) {// BooleanLogicTreeNode.NodeType.AND) {
- // root.setType(BooleanLogicTreeNode.NodeType.OR);
- root.setType(ParserTreeConstants.JJTORNODE);
- } else if (root.getType() == ParserTreeConstants.JJTORNODE) {// BooleanLogicTreeNode.NodeType.OR) {
- // root.setType(BooleanLogicTreeNode.NodeType.AND);
- root.setType(ParserTreeConstants.JJTANDNODE);
- } else if (root.getType() == ParserTreeConstants.JJTEQNODE || root.getType() == ParserTreeConstants.JJTERNODE) {
- // do nothing
- } else {
- log.error("refactorSubTree, node type not supported");
- }
-
- Enumeration<?> children = root.children();
- RewriterTreeNode child = null;
- // now distribute the negative
-
- while (children.hasMoreElements()) {
- child = (RewriterTreeNode) children.nextElement();
- if (child.isNegated()) {
- child.setNegated(false);
- } else {
- child.setNegated(true);
- }
- }
- }
-
- private RewriterTreeNode applyCaseSensitivity(RewriterTreeNode root, boolean fnUpper, boolean fvUpper) {
- // for each leaf, apply case sensitivity
- Enumeration<?> bfe = root.breadthFirstEnumeration();
- while (bfe.hasMoreElements()) {
- RewriterTreeNode node = (RewriterTreeNode) bfe.nextElement();
- if (node.isLeaf()) {
- String fName = fnUpper ? node.getFieldName().toUpperCase() : node.getFieldName().toLowerCase();
- node.setFieldName(fName);
-
- String fValue = fvUpper ? node.getFieldValue().toUpperCase() : node.getFieldValue().toLowerCase();
- node.setFieldValue(fValue);
-
- }
- }
- return root;
- }
-
- private Map<Text,RangeBounds> getBoundedRangeMap(RewriterTreeNode node) {
-
- if (node.getType() == ParserTreeConstants.JJTANDNODE || node.getType() == ParserTreeConstants.JJTORNODE) {
- Enumeration<?> children = node.children();
- Map<Text,RangeBounds> rangeMap = new HashMap<Text,RangeBounds>();
- while (children.hasMoreElements()) {
- RewriterTreeNode child = (RewriterTreeNode) children.nextElement();
- if (child.getType() == ParserTreeConstants.JJTLENODE || child.getType() == ParserTreeConstants.JJTLTNODE) {
- Text fName = new Text(child.getFieldName());
- if (rangeMap.containsKey(fName)) {
- RangeBounds rb = rangeMap.get(fName);
- if (rb.getLower() != null) {
- log.error("testBoundedRangeExistence, two lower bounds exist for bounded range.");
- }
- rb.setLower(new Text(child.getFieldValue()));
- } else {
- RangeBounds rb = new RangeBounds();
- rb.setLower(new Text(child.getFieldValue()));
- rangeMap.put(new Text(child.getFieldName()), rb);
- }
-
- } else if (child.getType() == ParserTreeConstants.JJTGENODE || child.getType() == ParserTreeConstants.JJTGTNODE) {
- Text fName = new Text(child.getFieldName());
- if (rangeMap.containsKey(fName)) {
- RangeBounds rb = rangeMap.get(fName);
- if (rb.getUpper() != null) {
- log.error("testBoundedRangeExistence, two Upper bounds exist for bounded range.");
- }
- rb.setUpper(new Text(child.getFieldValue()));
- } else {
- RangeBounds rb = new RangeBounds();
- rb.setUpper(new Text(child.getFieldValue()));
- rangeMap.put(new Text(child.getFieldName()), rb);
- }
- }
- }
-
- for (Entry<Text,RangeBounds> entry : rangeMap.entrySet()) {
- RangeBounds rb = entry.getValue();
- if (rb.getLower() == null || rb.getUpper() == null) {
- // unbounded range, remove
- if (log.isDebugEnabled()) {
- log.debug("testBoundedRangeExistence: Unbounded Range detected, removing entry from rangeMap");
- }
- rangeMap.remove(entry.getKey());
- }
- }
- if (!rangeMap.isEmpty()) {
- return rangeMap;
- }
- }
-
- return null;
- }
-
- /**
- * INNER CLASSES
- */
- public class RewriterTreeNode extends DefaultMutableTreeNode {
-
- private static final long serialVersionUID = 1L;
- private boolean negated = false;
- private String fieldName;
- private String fieldValue;
- private String operator;
- private int type;
- private boolean removal = false;
-
- /**
- *
- * @param type
- */
- public RewriterTreeNode(int type) {
- super();
- this.type = type;
- }
-
- /**
- *
- * @param type
- * @param fName
- * @param fValue
- */
- public RewriterTreeNode(int type, String fName, String fValue) {
- super();
- init(type, fName, fValue);
- }
-
- /**
- *
- * @param type
- * @param fName
- * @param fValue
- * @param negate
- */
- public RewriterTreeNode(int type, String fName, String fValue, boolean negate) {
- super();
- init(type, fName, fValue, negate);
- }
-
- private void init(int type, String fName, String fValue) {
- init(type, fName, fValue, false);
- }
-
- private void init(int type, String fName, String fValue, boolean negate) {
- this.type = type;
- this.fieldName = fName;
- this.fieldValue = fValue;
- this.negated = negate;
- this.operator = JexlOperatorConstants.getOperator(type);
- if (log.isDebugEnabled()) {
- log.debug("FN: " + this.fieldName + " FV: " + this.fieldValue + " Op: " + this.operator);
- }
- }
-
- /**
- * @return The field name.
- */
- public String getFieldName() {
- return fieldName;
- }
-
- /**
- *
- * @param fieldName
- */
- public void setFieldName(String fieldName) {
- this.fieldName = fieldName;
- }
-
- /**
- *
- * @return The field value.
- */
- public String getFieldValue() {
- return fieldValue;
- }
-
- /**
- *
- * @param fieldValue
- */
- public void setFieldValue(String fieldValue) {
- this.fieldValue = fieldValue;
- }
-
- /**
- *
- * @return true if negated, otherwise false.
- */
- public boolean isNegated() {
- return negated;
- }
-
- /**
- *
- * @param negated
- */
- public void setNegated(boolean negated) {
- this.negated = negated;
- }
-
- /**
- *
- * @return The operator.
- */
- public String getOperator() {
- return operator;
- }
-
- /**
- *
- * @param operator
- */
- public void setOperator(String operator) {
- this.operator = operator;
- }
-
- /**
- *
- * @return The type.
- */
- public int getType() {
- return type;
- }
-
- /**
- *
- * @param type
- */
- public void setType(int type) {
- this.type = type;
- }
-
- public boolean isRemoval() {
- return removal;
- }
-
- public void setRemoval(boolean removal) {
- this.removal = removal;
- }
-
- public String getContents() {
- StringBuilder s = new StringBuilder("[");
- s.append(toString());
-
- if (children != null) {
- Enumeration<?> e = this.children();
- while (e.hasMoreElements()) {
- RewriterTreeNode n = (RewriterTreeNode) e.nextElement();
- s.append(",");
- s.append(n.getContents());
- }
- }
- s.append("]");
- return s.toString();
- }
-
- /**
- *
- * @return A string represenation of the field name and value.
- */
- public String printNode() {
- StringBuilder s = new StringBuilder("[");
- s.append("Full Location & Term = ");
- if (this.fieldName != null) {
- s.append(this.fieldName.toString());
- } else {
- s.append("BlankDataLocation");
- }
- s.append(" ");
- if (this.fieldValue != null) {
- s.append(this.fieldValue.toString());
- } else {
- s.append("BlankTerm");
- }
- s.append("]");
- return s.toString();
- }
-
- @Override
- public String toString() {
- switch (type) {
- case ParserTreeConstants.JJTEQNODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTNENODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTERNODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTNRNODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTLENODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTLTNODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTGENODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTGTNODE:
- return fieldName + ":" + fieldValue + ":negated=" + isNegated();
- case ParserTreeConstants.JJTJEXLSCRIPT:
- return "HEAD";
- case ParserTreeConstants.JJTANDNODE:
- return "AND";
- case ParserTreeConstants.JJTNOTNODE:
- return "NOT";
- case ParserTreeConstants.JJTORNODE:
- return "OR";
- default:
- System.out.println("Problem in NuwaveTreeNode.toString()");
- return null;
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/8db62992/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/JexlOperatorConstants.java
----------------------------------------------------------------------
diff --git a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/JexlOperatorConstants.java b/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/JexlOperatorConstants.java
deleted file mode 100644
index 29898a3..0000000
--- a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/JexlOperatorConstants.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.parser;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-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.ASTFunctionNode;
-import org.apache.commons.jexl2.parser.ASTGENode;
-import org.apache.commons.jexl2.parser.ASTGTNode;
-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.ASTOrNode;
-import org.apache.commons.jexl2.parser.JexlNode;
-import org.apache.commons.jexl2.parser.ParserTreeConstants;
-
-public class JexlOperatorConstants implements ParserTreeConstants {
-
- private static Map<Class<? extends JexlNode>,String> operatorMap = new ConcurrentHashMap<Class<? extends JexlNode>,String>();
- private static Map<String,Class<? extends JexlNode>> classMap = new ConcurrentHashMap<String,Class<? extends JexlNode>>();
- private static Map<Integer,String> jjtOperatorMap = new ConcurrentHashMap<Integer,String>();
- private static Map<String,Integer> jjtTypeMap = new ConcurrentHashMap<String,Integer>();
-
- static {
- operatorMap.put(ASTEQNode.class, "==");
- operatorMap.put(ASTNENode.class, "!=");
- operatorMap.put(ASTLTNode.class, "<");
- operatorMap.put(ASTLENode.class, "<=");
- operatorMap.put(ASTGTNode.class, ">");
- operatorMap.put(ASTGENode.class, ">=");
- operatorMap.put(ASTERNode.class, "=~");
- operatorMap.put(ASTNRNode.class, "!~");
- operatorMap.put(ASTFunctionNode.class, "f");
- operatorMap.put(ASTAndNode.class, "and");
- operatorMap.put(ASTOrNode.class, "or");
-
- classMap.put("==", ASTEQNode.class);
- classMap.put("!=", ASTNENode.class);
- classMap.put("<", ASTLTNode.class);
- classMap.put("<=", ASTLENode.class);
- classMap.put(">", ASTGTNode.class);
- classMap.put(">=", ASTGENode.class);
- classMap.put("=~", ASTERNode.class);
- classMap.put("!~", ASTNRNode.class);
- classMap.put("f", ASTFunctionNode.class);
-
- jjtOperatorMap.put(JJTEQNODE, "==");
- jjtOperatorMap.put(JJTNENODE, "!=");
- jjtOperatorMap.put(JJTLTNODE, "<");
- jjtOperatorMap.put(JJTLENODE, "<=");
- jjtOperatorMap.put(JJTGTNODE, ">");
- jjtOperatorMap.put(JJTGENODE, ">=");
- jjtOperatorMap.put(JJTERNODE, "=~");
- jjtOperatorMap.put(JJTNRNODE, "!~");
- jjtOperatorMap.put(JJTFUNCTIONNODE, "f");
- jjtOperatorMap.put(JJTANDNODE, "and");
- jjtOperatorMap.put(JJTORNODE, "or");
-
- jjtTypeMap.put("==", JJTEQNODE);
- jjtTypeMap.put("!=", JJTNENODE);
- jjtTypeMap.put("<", JJTLTNODE);
- jjtTypeMap.put("<=", JJTLENODE);
- jjtTypeMap.put(">", JJTGTNODE);
- jjtTypeMap.put(">=", JJTGENODE);
- jjtTypeMap.put("=~", JJTERNODE);
- jjtTypeMap.put("!~", JJTNRNODE);
- jjtTypeMap.put("f", JJTFUNCTIONNODE);
-
- }
-
- public static String getOperator(Class<? extends JexlNode> nodeType) {
- return operatorMap.get(nodeType);
- }
-
- public static String getOperator(Integer jjtNode) {
- return jjtOperatorMap.get(jjtNode);
- }
-
- public static Class<? extends JexlNode> getClass(String operator) {
- return classMap.get(operator);
- }
-
- public static int getJJTNodeType(String operator) {
- return jjtTypeMap.get(operator);
- }
-}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/8db62992/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/QueryEvaluator.java
----------------------------------------------------------------------
diff --git a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/QueryEvaluator.java b/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/QueryEvaluator.java
deleted file mode 100644
index aaac3d8..0000000
--- a/src/examples/wikisearch/query/src/main/java/org/apache/accumulo/examples/wikisearch/parser/QueryEvaluator.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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.parser;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-
-import org.apache.accumulo.examples.wikisearch.function.QueryFunctions;
-import org.apache.accumulo.examples.wikisearch.jexl.Arithmetic;
-import org.apache.accumulo.examples.wikisearch.parser.EventFields.FieldValue;
-import org.apache.accumulo.examples.wikisearch.parser.QueryParser.QueryTerm;
-import org.apache.commons.jexl2.Expression;
-import org.apache.commons.jexl2.JexlContext;
-import org.apache.commons.jexl2.JexlEngine;
-import org.apache.commons.jexl2.MapContext;
-import org.apache.commons.jexl2.Script;
-import org.apache.commons.jexl2.parser.ParseException;
-import org.apache.commons.jexl2.parser.ParserTreeConstants;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-
-
-import com.google.common.collect.Multimap;
-
-
-/**
- * This class evaluates events against a query. The query is passed to the constructor and then parsed. It is evaluated against an event in the evaluate method.
- */
-public class QueryEvaluator {
-
- private static Logger log = Logger.getLogger(QueryEvaluator.class);
- // According to the JEXL 2.0 docs, the engine is thread-safe. Let's create 1 engine per VM and
- // cache 128 expressions
- private static JexlEngine engine = new JexlEngine(null, new Arithmetic(false), null, null);
-
- static {
- engine.setSilent(false);
- engine.setCache(128);
- Map<String,Object> functions = new HashMap<String,Object>();
- functions.put("f", QueryFunctions.class);
- engine.setFunctions(functions);
- }
- private String query = null;
- private Set<String> literals = null;
- private Multimap<String,QueryTerm> terms = null;
- private String modifiedQuery = null;
- private JexlContext ctx = new MapContext();
- private boolean caseInsensitive = true;
-
- public QueryEvaluator(String query) throws ParseException {
- this.caseInsensitive = true; // default case insensitive matching.
- if (caseInsensitive) {
- query = query.toLowerCase();
- }
- this.query = query;
- QueryParser parser = new QueryParser();
- parser.execute(query);
- this.terms = parser.getQueryTerms();
- if (caseInsensitive) {
- literals = new HashSet<String>();
- for (String lit : parser.getQueryIdentifiers()) {
- literals.add(lit.toLowerCase());
- }
- } else {
- this.literals = parser.getQueryIdentifiers();
- }
- }
-
- public QueryEvaluator(String query, boolean insensitive) throws ParseException {
- this.caseInsensitive = insensitive;
- if (this.caseInsensitive) {
- query = query.toLowerCase();
- }
- this.query = query;
- QueryParser parser = new QueryParser();
- parser.execute(query);
- this.terms = parser.getQueryTerms();
-
- if (caseInsensitive) {
- literals = new HashSet<String>();
- for (String lit : parser.getQueryIdentifiers()) {
- literals.add(lit.toLowerCase());
- }
- } else {
- this.literals = parser.getQueryIdentifiers();
- }
- }
-
- public String getQuery() {
- return this.query;
- }
-
- public void printLiterals() {
- for (String s : literals) {
- System.out.println("literal: " + s);
- }
- }
-
- public void setLevel(Level lev) {
- log.setLevel(lev);
- }
-
- public StringBuilder rewriteQuery(StringBuilder query, String fieldName, Collection<FieldValue> fieldValues) {
- if (log.isDebugEnabled()) {
- log.debug("rewriteQuery");
- }
- // Here we have a field that has multiple values. In this case we need to put
- // all values into the jexl context as an array and rewrite the query to account for all
- // of the fields.
- if (caseInsensitive) {
- fieldName = fieldName.toLowerCase();
- }
- if (log.isDebugEnabled()) {
- log.debug("Modifying original query: " + query);
- }
- // Pull the values out of the FieldValue object
- String[] values = new String[fieldValues.size()];
- int idx = 0;
- for (FieldValue fv : fieldValues) {
- if (caseInsensitive) {
- values[idx] = (new String(fv.getValue())).toLowerCase();
- } else {
- values[idx] = new String(fv.getValue());
- }
- idx++;
- }
- // Add the array to the context
- ctx.set(fieldName, values);
-
- Collection<QueryTerm> qt = terms.get(fieldName);
-
- // Add a script to the beginning of the query for this multi-valued field
- StringBuilder script = new StringBuilder();
- script.append("_").append(fieldName).append(" = false;\n");
- script.append("for (field : ").append(fieldName).append(") {\n");
-
- for (QueryTerm t : qt) {
- if (!t.getOperator().equals(JexlOperatorConstants.getOperator(ParserTreeConstants.JJTFUNCTIONNODE))) {
- script.append("\tif (_").append(fieldName).append(" == false && field ").append(t.getOperator()).append(" ").append(t.getValue()).append(") { \n");
- } else {
- script.append("\tif (_").append(fieldName).append(" == false && ").append(t.getValue().toString().replace(fieldName, "field")).append(") { \n");
- }
- script.append("\t\t_").append(fieldName).append(" = true;\n");
- script.append("\t}\n");
- }
- script.append("}\n");
-
- // Add the script to the beginning of the query
- query.insert(0, script.toString());
-
- StringBuilder newPredicate = new StringBuilder();
- newPredicate.append("_").append(fieldName).append(" == true");
-
- for (QueryTerm t : qt) {
- // Find the location of this term in the query
- StringBuilder predicate = new StringBuilder();
- int start = 0;
- if (!t.getOperator().equals(JexlOperatorConstants.getOperator(ParserTreeConstants.JJTFUNCTIONNODE))) {
- predicate.append(fieldName).append(" ").append(t.getOperator()).append(" ").append(t.getValue());
- start = query.indexOf(predicate.toString());
- } else {
- predicate.append(t.getValue().toString());
- // need to find the second occurence of the string.
- start = query.indexOf(predicate.toString());
- }
- if (-1 == start) {
- log.warn("Unable to find predicate: " + predicate.toString() + " in rewritten query: " + query.toString());
- }
- int length = predicate.length();
-
- // Now modify the query to check the value of my.fieldName
- query.replace(start, start + length, newPredicate.toString());
- }
-
- if (log.isDebugEnabled()) {
- log.debug("leaving rewriteQuery with: " + query.toString());
- }
- return query;
- }
-
- /**
- * Evaluates the query against an event.
- *
- * @param eventFields
- */
- public boolean evaluate(EventFields eventFields) {
-
- this.modifiedQuery = null;
- boolean rewritten = false;
-
- // Copy the query
- StringBuilder q = new StringBuilder(query);
- // Copy the literals, we are going to remove elements from this set
- // when they are added to the JEXL context. This will allow us to
- // determine which items in the query where *NOT* in the data.
- HashSet<String> literalsCopy = new HashSet<String>(literals);
-
- // Loop through the event fields and add them to the JexlContext.
- for (Entry<String,Collection<FieldValue>> field : eventFields.asMap().entrySet()) {
- String fName = field.getKey();
- if (caseInsensitive) {
- fName = fName.toLowerCase();
- }
- // If this field is not part of the expression, then skip it.
- if (!literals.contains(fName)) {
- continue;
- } else {
- literalsCopy.remove(fName);
- }
-
- // This field may have multiple values.
- if (field.getValue().size() == 0) {
- continue;
- } else if (field.getValue().size() == 1) {
- // We are explicitly converting these bytes to a String.
- if (caseInsensitive) {
- ctx.set(field.getKey().toLowerCase(), (new String(field.getValue().iterator().next().getValue())).toLowerCase());
- } else {
- ctx.set(field.getKey(), new String(field.getValue().iterator().next().getValue()));
- }
-
- } else {
- // q = queryRewrite(q, field.getKey(), field.getValue());
- q = rewriteQuery(q, field.getKey(), field.getValue());
- rewritten = true;
- }// End of if
-
- }// End of loop
-
- // For any literals in the query that were not found in the data, add them to the context
- // with a null value.
- for (String lit : literalsCopy) {
- ctx.set(lit, null);
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Evaluating query: " + q.toString());
- }
-
- this.modifiedQuery = q.toString();
-
- Boolean result = null;
- if (rewritten) {
- Script script = engine.createScript(this.modifiedQuery);
- try {
- result = (Boolean) script.execute(ctx);
- } catch (Exception e) {
- log.error("Error evaluating script: " + this.modifiedQuery + " against event" + eventFields.toString(), e);
- }
- } else {
- Expression expr = engine.createExpression(this.modifiedQuery);
- try {
- result = (Boolean) expr.evaluate(ctx);
- } catch (Exception e) {
- log.error("Error evaluating expression: " + this.modifiedQuery + " against event" + eventFields.toString(), e);
- }
- }
- if (null != result && result) {
- return true;
- } else {
- return false;
- }
- } // End of method
-
- /**
- *
- * @return rewritten query that was evaluated against the most recent event
- */
- public String getModifiedQuery() {
- return this.modifiedQuery;
- }
-}