pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / queryparser / src / java / org / apache / lucene / queryParser / core / processors / QueryNodeProcessorImpl.java
diff --git a/lucene-java-3.5.0/lucene/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/processors/QueryNodeProcessorImpl.java b/lucene-java-3.5.0/lucene/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/processors/QueryNodeProcessorImpl.java
new file mode 100644 (file)
index 0000000..97bedd0
--- /dev/null
@@ -0,0 +1,253 @@
+package org.apache.lucene.queryParser.core.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+
+/**
+ * <p>
+ * This is a default implementation for the {@link QueryNodeProcessor}
+ * interface, it's an abstract class, so it should be extended by classes that
+ * want to process a {@link QueryNode} tree.
+ * </p>
+ * <p>
+ * This class process {@link QueryNode}s from left to right in the tree. While
+ * it's walking down the tree, for every node,
+ * {@link #preProcessNode(QueryNode)} is invoked. After a node's children are
+ * processed, {@link #postProcessNode(QueryNode)} is invoked for that node.
+ * {@link #setChildrenOrder(List)} is invoked before
+ * {@link #postProcessNode(QueryNode)} only if the node has at least one child,
+ * in {@link #setChildrenOrder(List)} the implementor might redefine the
+ * children order or remove any children from the children list.
+ * </p>
+ * <p>
+ * Here is an example about how it process the nodes:
+ * </p>
+ * 
+ * <pre>
+ *      a
+ *     / \
+ *    b   e
+ *   / \
+ *  c   d
+ * </pre>
+ * 
+ * Here is the order the methods would be invoked for the tree described above:
+ * 
+ * <pre>
+ *      preProcessNode( a );
+ *      preProcessNode( b );
+ *      preProcessNode( c );
+ *      postProcessNode( c );
+ *      preProcessNode( d );
+ *      postProcessNode( d );
+ *      setChildrenOrder( bChildrenList );
+ *      postProcessNode( b );
+ *      preProcessNode( e );
+ *      postProcessNode( e );
+ *      setChildrenOrder( aChildrenList );
+ *      postProcessNode( a )
+ * </pre>
+ * 
+ * @see org.apache.lucene.queryParser.core.processors.QueryNodeProcessor
+ */
+public abstract class QueryNodeProcessorImpl implements QueryNodeProcessor {
+
+  private ArrayList<ChildrenList> childrenListPool = new ArrayList<ChildrenList>();
+
+  private QueryConfigHandler queryConfig;
+
+  public QueryNodeProcessorImpl() {
+    // empty constructor
+  }
+
+  public QueryNodeProcessorImpl(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+  }
+
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+    return processIteration(queryTree);
+  }
+
+  private QueryNode processIteration(QueryNode queryTree)
+      throws QueryNodeException {
+    queryTree = preProcessNode(queryTree);
+
+    processChildren(queryTree);
+
+    queryTree = postProcessNode(queryTree);
+
+    return queryTree;
+
+  }
+
+  /**
+   * This method is called every time a child is processed.
+   * 
+   * @param queryTree
+   *          the query node child to be processed
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  protected void processChildren(QueryNode queryTree) throws QueryNodeException {
+
+    List<QueryNode> children = queryTree.getChildren();
+    ChildrenList newChildren;
+
+    if (children != null && children.size() > 0) {
+
+      newChildren = allocateChildrenList();
+
+      try {
+
+        for (QueryNode child : children) {
+          child = processIteration(child);
+
+          if (child == null) {
+            throw new NullPointerException();
+
+          }
+
+          newChildren.add(child);
+
+        }
+
+        List<QueryNode> orderedChildrenList = setChildrenOrder(newChildren);
+
+        queryTree.set(orderedChildrenList);
+
+      } finally {
+        newChildren.beingUsed = false;
+      }
+
+    }
+
+  }
+
+  private ChildrenList allocateChildrenList() {
+    ChildrenList list = null;
+
+    for (ChildrenList auxList : this.childrenListPool) {
+
+      if (!auxList.beingUsed) {
+        list = auxList;
+        list.clear();
+
+        break;
+
+      }
+
+    }
+
+    if (list == null) {
+      list = new ChildrenList();
+      this.childrenListPool.add(list);
+
+    }
+
+    list.beingUsed = true;
+
+    return list;
+
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)}.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#getQueryConfigHandler()
+   * @see QueryConfigHandler
+   */
+  public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#getQueryConfigHandler()}.
+   * 
+   * @return QueryConfigHandler the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)
+   * @see QueryConfigHandler
+   */
+  public QueryConfigHandler getQueryConfigHandler() {
+    return this.queryConfig;
+  }
+
+  /**
+   * This method is invoked for every node when walking down the tree.
+   * 
+   * @param node
+   *          the query node to be pre-processed
+   * 
+   * @return a query node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected QueryNode preProcessNode(QueryNode node)
+      throws QueryNodeException;
+
+  /**
+   * This method is invoked for every node when walking up the tree.
+   * 
+   * @param node
+   *          node the query node to be post-processed
+   * 
+   * @return a query node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected QueryNode postProcessNode(QueryNode node)
+      throws QueryNodeException;
+
+  /**
+   * This method is invoked for every node that has at least on child. It's
+   * invoked right before {@link #postProcessNode(QueryNode)} is invoked.
+   * 
+   * @param children
+   *          the list containing all current node's children
+   * 
+   * @return a new list containing all children that should be set to the
+   *         current node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException;
+
+  private static class ChildrenList extends ArrayList<QueryNode> {
+
+    private static final long serialVersionUID = -2613518456949297135L;
+
+    boolean beingUsed;
+
+  }
+
+}