pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / queryparser / src / java / org / apache / lucene / queryParser / core / nodes / QueryNodeImpl.java
1 package org.apache.lucene.queryParser.core.nodes;
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.HashMap;
22 import java.util.Hashtable;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.ResourceBundle;
26
27 import org.apache.lucene.messages.NLS;
28 import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
29 import org.apache.lucene.queryParser.core.util.StringUtils;
30
31 /**
32  * A {@link QueryNodeImpl} is the default implementation of the interface
33  * {@link QueryNode}
34  */
35 public abstract class QueryNodeImpl implements QueryNode, Cloneable {
36
37   private static final long serialVersionUID = 5569870883474845989L;
38
39   /* index default field */
40   // TODO remove PLAINTEXT_FIELD_NAME replacing it with configuration APIs
41   public static final String PLAINTEXT_FIELD_NAME = "_plain";
42
43   private boolean isLeaf = true;
44
45   private Hashtable<String, Object> tags = new Hashtable<String, Object>();
46
47   private List<QueryNode> clauses = null;
48
49   protected void allocate() {
50
51     if (this.clauses == null) {
52       this.clauses = new ArrayList<QueryNode>();
53
54     } else {
55       this.clauses.clear();
56     }
57
58   }
59
60   public final void add(QueryNode child) {
61
62     if (isLeaf() || this.clauses == null || child == null) {
63       throw new IllegalArgumentException(NLS
64           .getLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
65     }
66
67     this.clauses.add(child);
68     ((QueryNodeImpl) child).setParent(this);
69
70   }
71
72   public final void add(List<QueryNode> children) {
73
74     if (isLeaf() || this.clauses == null) {
75       throw new IllegalArgumentException(NLS
76           .getLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
77     }
78
79     for (QueryNode child : children) {
80       add(child);
81     }
82
83   }
84
85   public boolean isLeaf() {
86     return this.isLeaf;
87   }
88
89   public final void set(List<QueryNode> children) {
90
91     if (isLeaf() || this.clauses == null) {
92       ResourceBundle bundle = ResourceBundle
93           .getBundle("org.apache.lucene.queryParser.messages.QueryParserMessages");
94       String message = bundle.getObject("Q0008E.NODE_ACTION_NOT_SUPPORTED")
95           .toString();
96
97       throw new IllegalArgumentException(message);
98
99     }
100
101     // reset parent value
102     for (QueryNode child : children) {
103
104       ((QueryNodeImpl) child).setParent(null);
105
106     }
107
108     // allocate new children list
109     allocate();
110
111     // add new children and set parent
112     for (QueryNode child : children) {
113       add(child);
114     }
115   }
116
117   public QueryNode cloneTree() throws CloneNotSupportedException {
118     QueryNodeImpl clone = (QueryNodeImpl) super.clone();
119     clone.isLeaf = this.isLeaf;
120
121     // Reset all tags
122     clone.tags = new Hashtable<String, Object>();
123
124     // copy children
125     if (this.clauses != null) {
126       List<QueryNode> localClauses = new ArrayList<QueryNode>();
127       for (QueryNode clause : this.clauses) {
128         localClauses.add(clause.cloneTree());
129       }
130       clone.clauses = localClauses;
131     }
132
133     return clone;
134   }
135
136   @Override
137   public Object clone() throws CloneNotSupportedException {
138     return cloneTree();
139   }
140
141   protected void setLeaf(boolean isLeaf) {
142     this.isLeaf = isLeaf;
143   }
144
145   /**
146    * @return a List for QueryNode object. Returns null, for nodes that do not
147    *         contain children. All leaf Nodes return null.
148    */
149   public final List<QueryNode> getChildren() {
150     if (isLeaf() || this.clauses == null) {
151       return null;
152     }
153     return this.clauses;
154   }
155
156   /**
157    * @deprecated use {@link #setTag(String, Object)} instead
158    */
159   @Deprecated
160   public void setTag(CharSequence tagName, Object value) {
161     this.tags.put(tagName.toString().toLowerCase(), value);
162   }
163
164   public void setTag(String tagName, Object value) {
165     this.tags.put(tagName.toLowerCase(), value);
166   }
167
168   public void unsetTag(String tagName) {
169     this.tags.remove(tagName.toLowerCase());
170   }
171
172   /**
173    * @deprecated use {@link #unsetTag(String)}
174    */
175   @Deprecated
176   public void unsetTag(CharSequence tagName) {
177     this.tags.remove(tagName.toString().toLowerCase());
178   }
179
180   /**
181    * verify if a node contains a tag
182    * 
183    * @deprecated use {@link #containsTag(String)} instead
184    */
185   @Deprecated
186   public boolean containsTag(CharSequence tagName) {
187     return this.tags.containsKey(tagName.toString().toLowerCase());
188   }
189
190   /** verify if a node contains a tag */
191   public boolean containsTag(String tagName) {
192     return this.tags.containsKey(tagName.toLowerCase());
193   }
194
195   /**
196    * @deprecated use {@link #getTag(String)} instead
197    */
198   @Deprecated
199   public Object getTag(CharSequence tagName) {
200     return this.tags.get(tagName.toString().toLowerCase());
201   }
202
203   public Object getTag(String tagName) {
204     return this.tags.get(tagName.toString().toLowerCase());
205   }
206
207   private QueryNode parent = null;
208
209   private void setParent(QueryNode parent) {
210     this.parent = parent;
211   }
212
213   public QueryNode getParent() {
214     return this.parent;
215   }
216
217   protected boolean isRoot() {
218     return getParent() == null;
219   }
220
221   /**
222    * If set to true the the method toQueryString will not write field names
223    */
224   protected boolean toQueryStringIgnoreFields = false;
225
226   /**
227    * This method is use toQueryString to detect if fld is the default field
228    * 
229    * @param fld - field name
230    * @return true if fld is the default field
231    */
232   // TODO: remove this method, it's commonly used by {@link
233   // #toQueryString(org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax)}
234   // to figure out what is the default field, however, {@link
235   // #toQueryString(org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax)}
236   // should receive the default field value directly by parameter
237   protected boolean isDefaultField(CharSequence fld) {
238     if (this.toQueryStringIgnoreFields)
239       return true;
240     if (fld == null)
241       return true;
242     if (QueryNodeImpl.PLAINTEXT_FIELD_NAME.equals(StringUtils.toString(fld)))
243       return true;
244     return false;
245   }
246
247   /**
248    * Every implementation of this class should return pseudo xml like this:
249    * 
250    * For FieldQueryNode: <field start='1' end='2' field='subject' text='foo'/>
251    * 
252    * @see org.apache.lucene.queryParser.core.nodes.QueryNode#toString()
253    */
254   @Override
255   public String toString() {
256     return super.toString();
257   }
258
259   /**
260    * @see org.apache.lucene.queryParser.core.nodes.QueryNode#getTag(String)
261    * @return a Map with all tags for this QueryNode
262    * 
263    * @deprecated use {@link #getTagMap()} instead
264    */
265   @SuppressWarnings( { "unchecked" })
266   @Deprecated
267   public Map<CharSequence, Object> getTags() {
268     Map<String, Object> map = (Map<String, Object>) this.tags.clone();
269     Map<CharSequence, Object> charSeqMap = new HashMap<CharSequence, Object>();
270
271     for (String key : map.keySet()) {
272       Object obj = map.get(key);
273       charSeqMap.put(key, obj);
274
275     }
276
277     return charSeqMap;
278
279   }
280
281   /**
282    * Returns a map containing all tags attached to this query node.
283    * 
284    * @return a map containing all tags attached to this query node
285    */
286   @SuppressWarnings("unchecked")
287   public Map<String, Object> getTagMap() {
288     return (Map<String, Object>) this.tags.clone();
289   }
290
291 } // end class QueryNodeImpl