pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / xml-query-parser / src / java / org / apache / lucene / xmlparser / builders / NumericRangeFilterBuilder.java
1 package org.apache.lucene.xmlparser.builders;
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.io.IOException;
21
22 import org.apache.lucene.index.IndexReader;
23 import org.apache.lucene.search.DocIdSet;
24 import org.apache.lucene.search.Filter;
25 import org.apache.lucene.search.NumericRangeFilter;
26 import org.apache.lucene.util.NumericUtils;
27 import org.apache.lucene.xmlparser.DOMUtils;
28 import org.apache.lucene.xmlparser.FilterBuilder;
29 import org.apache.lucene.xmlparser.ParserException;
30 import org.w3c.dom.Element;
31
32 /**
33  * Creates a {@link NumericRangeFilter}. The table below specifies the required
34  * attributes and the defaults if optional attributes are omitted. For more
35  * detail on what each of the attributes actually do, consult the documentation
36  * for {@link NumericRangeFilter}:
37  * <table>
38  * <tr>
39  * <th>Attribute name</th>
40  * <th>Values</th>
41  * <th>Required</th>
42  * <th>Default</th>
43  * </tr>
44  * <tr>
45  * <td>fieldName</td>
46  * <td>String</td>
47  * <td>Yes</td>
48  * <td>N/A</td>
49  * </tr>
50  * <tr>
51  * <td>lowerTerm</td>
52  * <td>Specified by <tt>type</tt></td>
53  * <td>Yes</td>
54  * <td>N/A</td>
55  * </tr>
56  * <tr>
57  * <td>upperTerm</td>
58  * <td>Specified by <tt>type</tt></td>
59  * <td>Yes</td>
60  * <td>N/A</td>
61  * </tr>
62  * <tr>
63  * <td>type</td>
64  * <td>int, long, float, double</td>
65  * <td>No</td>
66  * <td>int</td>
67  * </tr>
68  * <tr>
69  * <td>includeLower</td>
70  * <td>true, false</td>
71  * <td>No</td>
72  * <td>true</td>
73  * </tr>
74  * <tr>
75  * <td>includeUpper</td>
76  * <td>true, false</td>
77  * <td>No</td>
78  * <td>true</td>
79  * </tr>
80  * <tr>
81  * <td>precisionStep</td>
82  * <td>Integer</td>
83  * <td>No</td>
84  * <td>4</td>
85  * </tr>
86  * </table>
87  * <p>
88  * If an error occurs parsing the supplied <tt>lowerTerm</tt> or
89  * <tt>upperTerm</tt> into the numeric type specified by <tt>type</tt>, then the
90  * error will be silently ignored and the resulting filter will not match any
91  * documents.
92  */
93 public class NumericRangeFilterBuilder implements FilterBuilder {
94         private static final NoMatchFilter NO_MATCH_FILTER = new NoMatchFilter();
95
96         private boolean strictMode = false;
97
98         /**
99          * Specifies how this {@link NumericRangeFilterBuilder} will handle errors.
100          * <p>
101          * If this is set to true, {@link #getFilter(Element)} will throw a
102          * {@link ParserException} if it is unable to parse the lowerTerm or upperTerm
103          * into the appropriate numeric type. If this is set to false, then this
104          * exception will be silently ignored and the resulting filter will not match
105          * any documents.
106          * <p>
107          * Defaults to false.
108          * 
109          * @param strictMode
110          */
111         public void setStrictMode(boolean strictMode) {
112                 this.strictMode = strictMode;
113         }
114
115         public Filter getFilter(Element e) throws ParserException {
116                 String field = DOMUtils.getAttributeWithInheritanceOrFail(e, "fieldName");
117                 String lowerTerm = DOMUtils.getAttributeOrFail(e, "lowerTerm");
118                 String upperTerm = DOMUtils.getAttributeOrFail(e, "upperTerm");
119                 boolean lowerInclusive = DOMUtils.getAttribute(e, "includeLower", true);
120                 boolean upperInclusive = DOMUtils.getAttribute(e, "includeUpper", true);
121                 int precisionStep = DOMUtils.getAttribute(e, "precisionStep",  NumericUtils.PRECISION_STEP_DEFAULT);
122
123                 String type = DOMUtils.getAttribute(e, "type", "int");
124                 try {
125                         Filter filter;
126                         if (type.equalsIgnoreCase("int")) {
127                                 filter = NumericRangeFilter.newIntRange(field, precisionStep, Integer
128                                                 .valueOf(lowerTerm), Integer.valueOf(upperTerm), lowerInclusive,
129                                                 upperInclusive);
130                         } else if (type.equalsIgnoreCase("long")) {
131                                 filter = NumericRangeFilter.newLongRange(field, precisionStep, Long
132                                                 .valueOf(lowerTerm), Long.valueOf(upperTerm), lowerInclusive,
133                                                 upperInclusive);
134                         } else if (type.equalsIgnoreCase("double")) {
135                                 filter = NumericRangeFilter.newDoubleRange(field, precisionStep, Double
136                                                 .valueOf(lowerTerm), Double.valueOf(upperTerm), lowerInclusive,
137                                                 upperInclusive);
138                         } else if (type.equalsIgnoreCase("float")) {
139                                 filter = NumericRangeFilter.newFloatRange(field, precisionStep, Float
140                                                 .valueOf(lowerTerm), Float.valueOf(upperTerm), lowerInclusive,
141                                                 upperInclusive);
142                         } else {
143                                 throw new ParserException(
144                                                 "type attribute must be one of: [long, int, double, float]");
145                         }
146                         return filter;
147                 } catch (NumberFormatException nfe) {
148                         if (strictMode) {
149                                 throw new ParserException(
150                                                 "Could not parse lowerTerm or upperTerm into a number", nfe);
151                         }
152                         return NO_MATCH_FILTER;
153                 }
154         }
155
156         static class NoMatchFilter extends Filter {
157                 private static final long serialVersionUID = 1L;
158
159                 @Override
160                 public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
161                         return null;
162                 }
163
164         }
165 }