diff --git a/lucene/contrib/CHANGES.txt b/lucene/contrib/CHANGES.txt
index 0f372ae9572..97a2fbfaac2 100644
--- a/lucene/contrib/CHANGES.txt
+++ b/lucene/contrib/CHANGES.txt
@@ -74,6 +74,8 @@ API Changes
(Robert Muir, Uwe Schindler, Simon Willnauer)
New features
+ * LUCENE-2306: Add NumericRangeFilter and NumericRangeQuery support to XMLQueryParser.
+ (Jingkei Ly, via Mark Harwood)
* LUCENE-2102: Add a Turkish LowerCase Filter. TurkishLowerCaseFilter handles
Turkish and Azeri unique casing behavior correctly.
diff --git a/lucene/contrib/xml-query-parser/LuceneCoreQuery.dtd b/lucene/contrib/xml-query-parser/LuceneCoreQuery.dtd
index 8cf7c36d38f..fdeaf6f7d35 100644
--- a/lucene/contrib/xml-query-parser/LuceneCoreQuery.dtd
+++ b/lucene/contrib/xml-query-parser/LuceneCoreQuery.dtd
@@ -54,8 +54,8 @@
-
-
+
+
@@ -283,7 +283,60 @@ Passes content directly through to the standard LuceneQuery parser see "Lucene Q
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java
index fa2f61738cb..c84b90a2981 100644
--- a/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java
+++ b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java
@@ -70,13 +70,14 @@ public class CoreParser implements QueryBuilder
this.parser=parser;
filterFactory = new FilterBuilderFactory();
filterFactory.addBuilder("RangeFilter",new RangeFilterBuilder());
-
+ filterFactory.addBuilder("NumericRangeFilter",new NumericRangeFilterBuilder());
queryFactory = new QueryBuilderFactory();
queryFactory.addBuilder("TermQuery",new TermQueryBuilder());
queryFactory.addBuilder("TermsQuery",new TermsQueryBuilder(analyzer));
queryFactory.addBuilder("MatchAllDocsQuery",new MatchAllDocsQueryBuilder());
queryFactory.addBuilder("BooleanQuery",new BooleanQueryBuilder(queryFactory));
+ queryFactory.addBuilder("NumericRangeQuery",new NumericRangeQueryBuilder());
if(parser!=null)
{
queryFactory.addBuilder("UserQuery",new UserInputQueryBuilder(parser));
diff --git a/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeFilterBuilder.java b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeFilterBuilder.java
new file mode 100644
index 00000000000..c834f8e4d98
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeFilterBuilder.java
@@ -0,0 +1,165 @@
+package org.apache.lucene.xmlparser.builders;
+
+/**
+ * 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.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.DocIdSet;
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.search.NumericRangeFilter;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.lucene.xmlparser.DOMUtils;
+import org.apache.lucene.xmlparser.FilterBuilder;
+import org.apache.lucene.xmlparser.ParserException;
+import org.w3c.dom.Element;
+
+/**
+ * Creates a {@link NumericRangeFilter}. The table below specifies the required
+ * attributes and the defaults if optional attributes are omitted. For more
+ * detail on what each of the attributes actually do, consult the documentation
+ * for {@link NumericRangeFilter}:
+ *
+ *
+ * Attribute name |
+ * Values |
+ * Required |
+ * Default |
+ *
+ *
+ * fieldName |
+ * String |
+ * Yes |
+ * N/A |
+ *
+ *
+ * lowerTerm |
+ * Specified by type |
+ * Yes |
+ * N/A |
+ *
+ *
+ * upperTerm |
+ * Specified by type |
+ * Yes |
+ * N/A |
+ *
+ *
+ * type |
+ * int, long, float, double |
+ * No |
+ * int |
+ *
+ *
+ * includeLower |
+ * true, false |
+ * No |
+ * true |
+ *
+ *
+ * includeUpper |
+ * true, false |
+ * No |
+ * true |
+ *
+ *
+ * precisionStep |
+ * Integer |
+ * No |
+ * 4 |
+ *
+ *
+ *
+ * If an error occurs parsing the supplied lowerTerm or
+ * upperTerm into the numeric type specified by type, then the
+ * error will be silently ignored and the resulting filter will not match any
+ * documents.
+ */
+public class NumericRangeFilterBuilder implements FilterBuilder {
+ private static final NoMatchFilter NO_MATCH_FILTER = new NoMatchFilter();
+
+ private boolean strictMode = false;
+
+ /**
+ * Specifies how this {@link NumericRangeFilterBuilder} will handle errors.
+ *
+ * If this is set to true, {@link #getFilter(Element)} will throw a
+ * {@link ParserException} if it is unable to parse the lowerTerm or upperTerm
+ * into the appropriate numeric type. If this is set to false, then this
+ * exception will be silently ignored and the resulting filter will not match
+ * any documents.
+ *
+ * Defaults to false.
+ *
+ * @param strictMode
+ */
+ public void setStrictMode(boolean strictMode) {
+ this.strictMode = strictMode;
+ }
+
+ public Filter getFilter(Element e) throws ParserException {
+ String field = DOMUtils.getAttributeWithInheritanceOrFail(e, "fieldName");
+ String lowerTerm = DOMUtils.getAttributeOrFail(e, "lowerTerm");
+ String upperTerm = DOMUtils.getAttributeOrFail(e, "upperTerm");
+ boolean lowerInclusive = DOMUtils.getAttribute(e, "includeLower", true);
+ boolean upperInclusive = DOMUtils.getAttribute(e, "includeUpper", true);
+ int precisionStep = DOMUtils.getAttribute(e, "precisionStep", NumericUtils.PRECISION_STEP_DEFAULT);
+
+ String type = DOMUtils.getAttribute(e, "type", "int");
+ try {
+ Filter filter;
+ if (type.equalsIgnoreCase("int")) {
+ filter = NumericRangeFilter.newIntRange(field, precisionStep, Integer
+ .valueOf(lowerTerm), Integer.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("long")) {
+ filter = NumericRangeFilter.newLongRange(field, precisionStep, Long
+ .valueOf(lowerTerm), Long.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("double")) {
+ filter = NumericRangeFilter.newDoubleRange(field, precisionStep, Double
+ .valueOf(lowerTerm), Double.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("float")) {
+ filter = NumericRangeFilter.newFloatRange(field, precisionStep, Float
+ .valueOf(lowerTerm), Float.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else {
+ throw new ParserException(
+ "type attribute must be one of: [long, int, double, float]");
+ }
+ return filter;
+ } catch (NumberFormatException nfe) {
+ if (strictMode) {
+ throw new ParserException(
+ "Could not parse lowerTerm or upperTerm into a number", nfe);
+ }
+ return NO_MATCH_FILTER;
+ }
+ }
+
+ static class NoMatchFilter extends Filter {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
+ return null;
+ }
+
+ }
+}
diff --git a/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeQueryBuilder.java b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeQueryBuilder.java
new file mode 100644
index 00000000000..5cf129ab501
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/builders/NumericRangeQueryBuilder.java
@@ -0,0 +1,127 @@
+package org.apache.lucene.xmlparser.builders;
+
+/**
+ * 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 org.apache.lucene.search.NumericRangeQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.lucene.xmlparser.DOMUtils;
+import org.apache.lucene.xmlparser.ParserException;
+import org.apache.lucene.xmlparser.QueryBuilder;
+import org.w3c.dom.Element;
+
+/**
+ * Creates a {@link NumericRangeQuery}. The table below specifies the required
+ * attributes and the defaults if optional attributes are omitted. For more
+ * detail on what each of the attributes actually do, consult the documentation
+ * for {@link NumericRangeQuery}:
+ *
+ *
+ * Attribute name |
+ * Values |
+ * Required |
+ * Default |
+ *
+ *
+ * fieldName |
+ * String |
+ * Yes |
+ * N/A |
+ *
+ *
+ * lowerTerm |
+ * Specified by type |
+ * Yes |
+ * N/A |
+ *
+ *
+ * upperTerm |
+ * Specified by type |
+ * Yes |
+ * N/A |
+ *
+ *
+ * type |
+ * int, long, float, double |
+ * No |
+ * int |
+ *
+ *
+ * includeLower |
+ * true, false |
+ * No |
+ * true |
+ *
+ *
+ * includeUpper |
+ * true, false |
+ * No |
+ * true |
+ *
+ *
+ * precisionStep |
+ * Integer |
+ * No |
+ * 4 |
+ *
+ *
+ *
+ * A {@link ParserException} will be thrown if an error occurs parsing the
+ * supplied lowerTerm or upperTerm into the numeric type
+ * specified by type.
+ */
+public class NumericRangeQueryBuilder implements QueryBuilder {
+
+ public Query getQuery(Element e) throws ParserException {
+ String field = DOMUtils.getAttributeWithInheritanceOrFail(e, "fieldName");
+ String lowerTerm = DOMUtils.getAttributeOrFail(e, "lowerTerm");
+ String upperTerm = DOMUtils.getAttributeOrFail(e, "upperTerm");
+ boolean lowerInclusive = DOMUtils.getAttribute(e, "includeLower", true);
+ boolean upperInclusive = DOMUtils.getAttribute(e, "includeUpper", true);
+ int precisionStep = DOMUtils.getAttribute(e, "precisionStep", NumericUtils.PRECISION_STEP_DEFAULT);
+
+ String type = DOMUtils.getAttribute(e, "type", "int");
+ try {
+ Query filter;
+ if (type.equalsIgnoreCase("int")) {
+ filter = NumericRangeQuery.newIntRange(field, precisionStep, Integer
+ .valueOf(lowerTerm), Integer.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("long")) {
+ filter = NumericRangeQuery.newLongRange(field, precisionStep, Long
+ .valueOf(lowerTerm), Long.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("double")) {
+ filter = NumericRangeQuery.newDoubleRange(field, precisionStep, Double
+ .valueOf(lowerTerm), Double.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else if (type.equalsIgnoreCase("float")) {
+ filter = NumericRangeQuery.newFloatRange(field, precisionStep, Float
+ .valueOf(lowerTerm), Float.valueOf(upperTerm), lowerInclusive,
+ upperInclusive);
+ } else {
+ throw new ParserException(
+ "type attribute must be one of: [long, int, double, float]");
+ }
+ return filter;
+ } catch (NumberFormatException nfe) {
+ throw new ParserException(
+ "Could not parse lowerTerm or upperTerm into a number", nfe);
+ }
+ }
+}
diff --git a/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeFilterBuilderTestCase.java b/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeFilterBuilderTestCase.java
new file mode 100644
index 00000000000..8acf9227a03
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeFilterBuilderTestCase.java
@@ -0,0 +1,216 @@
+package com.apache.lucene.xmlparser.builders;
+
+/**
+ * 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.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriter.MaxFieldLength;
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.search.NumericRangeFilter;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.xmlparser.ParserException;
+import org.apache.lucene.xmlparser.builders.NumericRangeFilterBuilder;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class NumericRangeFilterBuilderTestCase extends TestCase {
+
+ public void testGetFilterHandleNumericParseErrorStrict() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(true);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ try {
+ filterBuilder.getFilter(doc.getDocumentElement());
+ } catch (ParserException e) {
+ return;
+ }
+ fail("Expected to throw " + ParserException.class);
+ }
+
+ public void testGetFilterHandleNumericParseError() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(false);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ Filter filter = filterBuilder.getFilter(doc.getDocumentElement());
+
+ RAMDirectory ramDir = new RAMDirectory();
+ IndexWriter writer = new IndexWriter(ramDir, null, MaxFieldLength.UNLIMITED);
+ try
+ {
+ IndexReader reader = IndexReader.open(ramDir, true);
+ try
+ {
+ assertNull(filter.getDocIdSet(reader));
+ }
+ finally
+ {
+ reader.close();
+ }
+ }
+ finally
+ {
+ writer.commit();
+ writer.close();
+ }
+ }
+
+ public void testGetFilterInt() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(true);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ Filter filter = filterBuilder.getFilter(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter = (NumericRangeFilter) filter;
+ assertEquals(Integer.valueOf(-1), numRangeFilter.getMin());
+ assertEquals(Integer.valueOf(10), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Filter filter2 = filterBuilder.getFilter(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter2 = (NumericRangeFilter) filter2;
+ assertEquals(Integer.valueOf(-1), numRangeFilter2.getMin());
+ assertEquals(Integer.valueOf(10), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterLong() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(true);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ Filter filter = filterBuilder.getFilter(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter = (NumericRangeFilter) filter;
+ assertEquals(Long.valueOf(-2321L), numRangeFilter.getMin());
+ assertEquals(Long.valueOf(60000000L), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Filter filter2 = filterBuilder.getFilter(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter2 = (NumericRangeFilter) filter2;
+ assertEquals(Long.valueOf(-2321L), numRangeFilter2.getMin());
+ assertEquals(Long.valueOf(60000000L), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterDouble() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(true);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+
+ Filter filter = filterBuilder.getFilter(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter = (NumericRangeFilter) filter;
+ assertEquals(Double.valueOf(-23.21d), numRangeFilter.getMin());
+ assertEquals(Double.valueOf(60000.00023d), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Filter filter2 = filterBuilder.getFilter(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter2 = (NumericRangeFilter) filter2;
+ assertEquals(Double.valueOf(-23.21d), numRangeFilter2.getMin());
+ assertEquals(Double.valueOf(60000.00023d), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterFloat() throws Exception {
+ NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+ filterBuilder.setStrictMode(true);
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+
+ Filter filter = filterBuilder.getFilter(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter = (NumericRangeFilter) filter;
+ assertEquals(Float.valueOf(-2.321432f), numRangeFilter.getMin());
+ assertEquals(Float.valueOf(32432.23f), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+
+ Filter filter2 = filterBuilder.getFilter(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeFilter>);
+ @SuppressWarnings("unchecked")
+ NumericRangeFilter numRangeFilter2 = (NumericRangeFilter) filter2;
+ assertEquals(Float.valueOf(-2.321432f), numRangeFilter2.getMin());
+ assertEquals(Float.valueOf(32432.23f), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ private static Document getDocumentFromString(String str)
+ throws SAXException, IOException, ParserConfigurationException {
+ InputStream is = new ByteArrayInputStream(str.getBytes());
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(is);
+ is.close();
+ return doc;
+ }
+
+}
diff --git a/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeQueryBuilderTestCase.java b/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeQueryBuilderTestCase.java
new file mode 100644
index 00000000000..1c9e81edd73
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/test/com/apache/lucene/xmlparser/builders/NumericRangeQueryBuilderTestCase.java
@@ -0,0 +1,178 @@
+package com.apache.lucene.xmlparser.builders;
+
+/**
+ * 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.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.search.NumericRangeQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.xmlparser.ParserException;
+import org.apache.lucene.xmlparser.builders.NumericRangeQueryBuilder;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class NumericRangeQueryBuilderTestCase extends TestCase {
+
+ public void testGetFilterHandleNumericParseErrorStrict() throws Exception {
+ NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ try {
+ filterBuilder.getQuery(doc.getDocumentElement());
+ } catch (ParserException e) {
+ return;
+ }
+ fail("Expected to throw " + ParserException.class);
+ }
+
+ public void testGetFilterInt() throws Exception {
+ NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ Query filter = filterBuilder.getQuery(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter = (NumericRangeQuery) filter;
+ assertEquals(Integer.valueOf(-1), numRangeFilter.getMin());
+ assertEquals(Integer.valueOf(10), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Query filter2 = filterBuilder.getQuery(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter2 = (NumericRangeQuery) filter2;
+ assertEquals(Integer.valueOf(-1), numRangeFilter2.getMin());
+ assertEquals(Integer.valueOf(10), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterLong() throws Exception {
+ NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+ Query filter = filterBuilder.getQuery(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter = (NumericRangeQuery) filter;
+ assertEquals(Long.valueOf(-2321L), numRangeFilter.getMin());
+ assertEquals(Long.valueOf(60000000L), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Query filter2 = filterBuilder.getQuery(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter2 = (NumericRangeQuery) filter2;
+ assertEquals(Long.valueOf(-2321L), numRangeFilter2.getMin());
+ assertEquals(Long.valueOf(60000000L), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterDouble() throws Exception {
+ NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+
+ Query filter = filterBuilder.getQuery(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter = (NumericRangeQuery) filter;
+ assertEquals(Double.valueOf(-23.21d), numRangeFilter.getMin());
+ assertEquals(Double.valueOf(60000.00023d), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+ Query filter2 = filterBuilder.getQuery(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter2 = (NumericRangeQuery) filter2;
+ assertEquals(Double.valueOf(-23.21d), numRangeFilter2.getMin());
+ assertEquals(Double.valueOf(60000.00023d), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ public void testGetFilterFloat() throws Exception {
+ NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+ String xml = "";
+ Document doc = getDocumentFromString(xml);
+
+ Query filter = filterBuilder.getQuery(doc.getDocumentElement());
+ assertTrue(filter instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter = (NumericRangeQuery) filter;
+ assertEquals(Float.valueOf(-2.321432f), numRangeFilter.getMin());
+ assertEquals(Float.valueOf(32432.23f), numRangeFilter.getMax());
+ assertEquals("AGE", numRangeFilter.getField());
+ assertTrue(numRangeFilter.includesMin());
+ assertTrue(numRangeFilter.includesMax());
+
+ String xml2 = "";
+ Document doc2 = getDocumentFromString(xml2);
+
+ Query filter2 = filterBuilder.getQuery(doc2.getDocumentElement());
+ assertTrue(filter2 instanceof NumericRangeQuery>);
+ @SuppressWarnings("unchecked")
+ NumericRangeQuery numRangeFilter2 = (NumericRangeQuery) filter2;
+ assertEquals(Float.valueOf(-2.321432f), numRangeFilter2.getMin());
+ assertEquals(Float.valueOf(32432.23f), numRangeFilter2.getMax());
+ assertEquals("AGE", numRangeFilter2.getField());
+ assertTrue(numRangeFilter2.includesMin());
+ assertFalse(numRangeFilter2.includesMax());
+ }
+
+ private static Document getDocumentFromString(String str)
+ throws SAXException, IOException, ParserConfigurationException {
+ InputStream is = new ByteArrayInputStream(str.getBytes());
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(is);
+ is.close();
+ return doc;
+ }
+
+}
diff --git a/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeFilterQuery.xml b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeFilterQuery.xml
new file mode 100644
index 00000000000..aed33bc2e66
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeFilterQuery.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ merger
+
+
+ sumitomo
+
+
+ bank
+
+
+
+
+
+
+
+
+
diff --git a/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeQueryQuery.xml b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeQueryQuery.xml
new file mode 100644
index 00000000000..f3c976b93b8
--- /dev/null
+++ b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/NumericRangeQueryQuery.xml
@@ -0,0 +1,15 @@
+
+
+
+ merger
+
+
+ sumitomo
+
+
+ bank
+
+
+
+
+
diff --git a/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java
index 599dc50d096..eaa56f80938 100644
--- a/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java
+++ b/lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java
@@ -8,6 +8,7 @@ import java.io.InputStreamReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Field;
+import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
@@ -70,6 +71,9 @@ public class TestParser extends LuceneTestCase {
org.apache.lucene.document.Document doc =new org.apache.lucene.document.Document();
doc.add(new Field("date",date,Field.Store.YES,Field.Index.ANALYZED));
doc.add(new Field("contents",content,Field.Store.YES,Field.Index.ANALYZED));
+ NumericField numericField = new NumericField("date2");
+ numericField.setIntValue(Integer.valueOf(date));
+ doc.add(numericField);
writer.addDocument(doc);
line=d.readLine();
}
@@ -191,6 +195,18 @@ public class TestParser extends LuceneTestCase {
assertEquals("DuplicateFilterQuery should produce 1 result ", 1,h);
}
+ public void testNumericRangeFilterQueryXML() throws ParserException, IOException
+ {
+ Query q=parse("NumericRangeFilterQuery.xml");
+ dumpResults("NumericRangeFilter", q, 5);
+ }
+
+ public void testNumericRangeQueryQueryXML() throws ParserException, IOException
+ {
+ Query q=parse("NumericRangeQueryQuery.xml");
+ dumpResults("NumericRangeQuery", q, 5);
+ }
+
//================= Helper methods ===================================