pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / queryparser / src / java / org / apache / lucene / queryParser / standard / processors / GroupQueryNodeProcessor.java
1 package org.apache.lucene.queryParser.standard.processors;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.apache.lucene.queryParser.core.QueryNodeException;
24 import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
25 import org.apache.lucene.queryParser.core.nodes.AndQueryNode;
26 import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
27 import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
28 import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
29 import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
30 import org.apache.lucene.queryParser.core.nodes.QueryNode;
31 import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode.Modifier;
32 import org.apache.lucene.queryParser.core.parser.SyntaxParser;
33 import org.apache.lucene.queryParser.core.processors.QueryNodeProcessor;
34 import org.apache.lucene.queryParser.standard.config.StandardQueryConfigHandler;
35 import org.apache.lucene.queryParser.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
36 import org.apache.lucene.queryParser.standard.config.StandardQueryConfigHandler.Operator;
37 import org.apache.lucene.queryParser.standard.nodes.BooleanModifierNode;
38
39 /**
40  * The {@link SyntaxParser}
41  * generates query node trees that consider the boolean operator precedence, but
42  * Lucene current syntax does not support boolean precedence, so this processor
43  * remove all the precedence and apply the equivalent modifier according to the
44  * boolean operation defined on an specific query node. <br/>
45  * <br/>
46  * If there is a {@link GroupQueryNode} in the query node tree, the query node
47  * tree is not merged with the one above it.
48  * 
49  * Example: TODO: describe a good example to show how this processor works
50  * 
51  * @see org.apache.lucene.queryParser.standard.config.StandardQueryConfigHandler
52  */
53 public class GroupQueryNodeProcessor implements QueryNodeProcessor {
54
55   private ArrayList<QueryNode> queryNodeList;
56
57   private boolean latestNodeVerified;
58
59   private QueryConfigHandler queryConfig;
60
61   private Boolean usingAnd = false;
62
63   public GroupQueryNodeProcessor() {
64     // empty constructor
65   }
66
67   public QueryNode process(QueryNode queryTree) throws QueryNodeException {
68     Operator defaultOperator = getQueryConfigHandler().get(ConfigurationKeys.DEFAULT_OPERATOR);
69     
70     if (defaultOperator == null) {
71       throw new IllegalArgumentException(
72           "DEFAULT_OPERATOR should be set on the QueryConfigHandler");
73     }
74
75     this.usingAnd = StandardQueryConfigHandler.Operator.AND == defaultOperator;
76
77     if (queryTree instanceof GroupQueryNode) {
78       queryTree = ((GroupQueryNode) queryTree).getChild();
79     }
80
81     this.queryNodeList = new ArrayList<QueryNode>();
82     this.latestNodeVerified = false;
83     readTree(queryTree);
84
85     List<QueryNode> actualQueryNodeList = this.queryNodeList;
86
87     for (int i = 0; i < actualQueryNodeList.size(); i++) {
88       QueryNode node = actualQueryNodeList.get(i);
89
90       if (node instanceof GroupQueryNode) {
91         actualQueryNodeList.set(i, process(node));
92       }
93
94     }
95
96     this.usingAnd = false;
97
98     if (queryTree instanceof BooleanQueryNode) {
99       queryTree.set(actualQueryNodeList);
100
101       return queryTree;
102
103     } else {
104       return new BooleanQueryNode(actualQueryNodeList);
105     }
106
107   }
108
109   /**
110    */
111   private QueryNode applyModifier(QueryNode node, QueryNode parent) {
112
113     if (this.usingAnd) {
114
115       if (parent instanceof OrQueryNode) {
116
117         if (node instanceof ModifierQueryNode) {
118
119           ModifierQueryNode modNode = (ModifierQueryNode) node;
120
121           if (modNode.getModifier() == Modifier.MOD_REQ) {
122             return modNode.getChild();
123           }
124
125         }
126
127       } else {
128
129         if (node instanceof ModifierQueryNode) {
130
131           ModifierQueryNode modNode = (ModifierQueryNode) node;
132
133           if (modNode.getModifier() == Modifier.MOD_NONE) {
134             return new BooleanModifierNode(modNode.getChild(), Modifier.MOD_REQ);
135           }
136
137         } else {
138           return new BooleanModifierNode(node, Modifier.MOD_REQ);
139         }
140
141       }
142
143     } else {
144
145       if (node.getParent() instanceof AndQueryNode) {
146
147         if (node instanceof ModifierQueryNode) {
148
149           ModifierQueryNode modNode = (ModifierQueryNode) node;
150
151           if (modNode.getModifier() == Modifier.MOD_NONE) {
152             return new BooleanModifierNode(modNode.getChild(), Modifier.MOD_REQ);
153           }
154
155         } else {
156           return new BooleanModifierNode(node, Modifier.MOD_REQ);
157         }
158
159       }
160
161     }
162
163     return node;
164
165   }
166
167   private void readTree(QueryNode node) {
168
169     if (node instanceof BooleanQueryNode) {
170       List<QueryNode> children = node.getChildren();
171
172       if (children != null && children.size() > 0) {
173
174         for (int i = 0; i < children.size() - 1; i++) {
175           readTree(children.get(i));
176         }
177
178         processNode(node);
179         readTree(children.get(children.size() - 1));
180
181       } else {
182         processNode(node);
183       }
184
185     } else {
186       processNode(node);
187     }
188
189   }
190
191   private void processNode(QueryNode node) {
192
193     if (node instanceof AndQueryNode || node instanceof OrQueryNode) {
194
195       if (!this.latestNodeVerified && !this.queryNodeList.isEmpty()) {
196         this.queryNodeList.add(applyModifier(this.queryNodeList
197             .remove(this.queryNodeList.size() - 1), node));
198         this.latestNodeVerified = true;
199
200       }
201
202     } else if (!(node instanceof BooleanQueryNode)) {
203       this.queryNodeList.add(applyModifier(node, node.getParent()));
204       this.latestNodeVerified = false;
205
206     }
207
208   }
209
210   public QueryConfigHandler getQueryConfigHandler() {
211     return this.queryConfig;
212   }
213
214   public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
215     this.queryConfig = queryConfigHandler;
216   }
217
218 }