You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2016/03/10 03:04:58 UTC

[1/3] lucene-solr git commit: LUCENE-7089, LUCENE-7075: add points to flexible queryparser to replace legacy numerics support

Repository: lucene-solr
Updated Branches:
  refs/heads/master f24810bdf -> 89cc676f2


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java
deleted file mode 100644
index c29573b..0000000
--- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard;
-
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.TimeZone;
-
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.LegacyDoubleField;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
-import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyLongField;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
-import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
-import org.apache.lucene.queryparser.flexible.standard.config.NumberDateFormat;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-import org.apache.lucene.queryparser.flexible.standard.parser.EscapeQuerySyntaxImpl;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TopDocs;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.util.TestUtil;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestNumericQueryParser extends LuceneTestCase {
-  
-  private static enum NumberType {
-    NEGATIVE, ZERO, POSITIVE;
-  }
-  
-  final private static int[] DATE_STYLES = {DateFormat.FULL, DateFormat.LONG,
-      DateFormat.MEDIUM, DateFormat.SHORT};
-  
-  final private static int PRECISION_STEP = 8;
-  final private static String FIELD_NAME = "field";
-  private static Locale LOCALE;
-  private static TimeZone TIMEZONE;
-  private static Map<String,Number> RANDOM_NUMBER_MAP;
-  private static EscapeQuerySyntax ESCAPER = new EscapeQuerySyntaxImpl();
-  final private static String DATE_FIELD_NAME = "date";
-  private static int DATE_STYLE;
-  private static int TIME_STYLE;
-  
-  private static Analyzer ANALYZER;
-  
-  private static NumberFormat NUMBER_FORMAT;
-  
-  private static StandardQueryParser qp;
-  
-  private static NumberDateFormat DATE_FORMAT;
-  
-  private static Directory directory = null;
-  private static IndexReader reader = null;
-  private static IndexSearcher searcher = null;
-  
-  private static boolean checkDateFormatSanity(DateFormat dateFormat, long date) {
-    try {
-      return date == dateFormat.parse(dateFormat.format(new Date(date)))
-        .getTime();
-    } catch (ParseException e) {
-      return false;
-    }
-  }
-  
-  @BeforeClass
-  public static void beforeClass() throws Exception {
-    ANALYZER = new MockAnalyzer(random());
-    
-    qp = new StandardQueryParser(ANALYZER);
-    
-    final HashMap<String,Number> randomNumberMap = new HashMap<>();
-    
-    SimpleDateFormat dateFormat;
-    long randomDate;
-    boolean dateFormatSanityCheckPass;
-    int count = 0;
-    do {
-      if (count > 100) {
-        fail("This test has problems to find a sane random DateFormat/NumberFormat. Stopped trying after 100 iterations.");
-      }
-      
-      dateFormatSanityCheckPass = true;
-      LOCALE = randomLocale(random());
-      TIMEZONE = randomTimeZone(random());
-      DATE_STYLE = randomDateStyle(random());
-      TIME_STYLE = randomDateStyle(random());
-      
-      // assumes localized date pattern will have at least year, month, day,
-      // hour, minute
-      dateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance(
-          DATE_STYLE, TIME_STYLE, LOCALE);
-      
-      // not all date patterns includes era, full year, timezone and second,
-      // so we add them here
-      dateFormat.applyPattern(dateFormat.toPattern() + " G s Z yyyy");
-      dateFormat.setTimeZone(TIMEZONE);
-      
-      DATE_FORMAT = new NumberDateFormat(dateFormat);
-      
-      do {
-        randomDate = random().nextLong();
-        
-        // prune date value so it doesn't pass in insane values to some
-        // calendars.
-        randomDate = randomDate % 3400000000000l;
-        
-        // truncate to second
-        randomDate = (randomDate / 1000L) * 1000L;
-        
-        // only positive values
-        randomDate = Math.abs(randomDate);
-      } while (randomDate == 0L);
-      
-      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, randomDate);
-      
-      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, 0);
-      
-      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat,
-          -randomDate);
-      
-      count++;
-    } while (!dateFormatSanityCheckPass);
-    
-    NUMBER_FORMAT = NumberFormat.getNumberInstance(LOCALE);
-    NUMBER_FORMAT.setMaximumFractionDigits((random().nextInt() & 20) + 1);
-    NUMBER_FORMAT.setMinimumFractionDigits((random().nextInt() & 20) + 1);
-    NUMBER_FORMAT.setMaximumIntegerDigits((random().nextInt() & 20) + 1);
-    NUMBER_FORMAT.setMinimumIntegerDigits((random().nextInt() & 20) + 1);
-    
-    double randomDouble;
-    long randomLong;
-    int randomInt;
-    float randomFloat;
-    
-    while ((randomLong = normalizeNumber(Math.abs(random().nextLong()))
-        .longValue()) == 0L)
-      ;
-    while ((randomDouble = normalizeNumber(Math.abs(random().nextDouble()))
-        .doubleValue()) == 0.0)
-      ;
-    while ((randomFloat = normalizeNumber(Math.abs(random().nextFloat()))
-        .floatValue()) == 0.0f)
-      ;
-    while ((randomInt = normalizeNumber(Math.abs(random().nextInt())).intValue()) == 0)
-      ;
-    
-    randomNumberMap.put(LegacyNumericType.LONG.name(), randomLong);
-    randomNumberMap.put(FieldType.LegacyNumericType.INT.name(), randomInt);
-    randomNumberMap.put(LegacyNumericType.FLOAT.name(), randomFloat);
-    randomNumberMap.put(LegacyNumericType.DOUBLE.name(), randomDouble);
-    randomNumberMap.put(DATE_FIELD_NAME, randomDate);
-    
-    RANDOM_NUMBER_MAP = Collections.unmodifiableMap(randomNumberMap);
-    
-    directory = newDirectory();
-    RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
-        newIndexWriterConfig(new MockAnalyzer(random()))
-            .setMaxBufferedDocs(TestUtil.nextInt(random(), 50, 1000))
-            .setMergePolicy(newLogMergePolicy()));
-    
-    Document doc = new Document();
-    HashMap<String,NumericConfig> numericConfigMap = new HashMap<>();
-    HashMap<String,Field> numericFieldMap = new HashMap<>();
-    qp.setNumericConfigMap(numericConfigMap);
-    
-    for (LegacyNumericType type : LegacyNumericType.values()) {
-      numericConfigMap.put(type.name(), new NumericConfig(PRECISION_STEP,
-          NUMBER_FORMAT, type));
-
-      FieldType ft = new FieldType(LegacyIntField.TYPE_NOT_STORED);
-      ft.setNumericType(type);
-      ft.setStored(true);
-      ft.setNumericPrecisionStep(PRECISION_STEP);
-      ft.freeze();
-      final Field field;
-
-      switch(type) {
-      case INT:
-        field = new LegacyIntField(type.name(), 0, ft);
-        break;
-      case FLOAT:
-        field = new LegacyFloatField(type.name(), 0.0f, ft);
-        break;
-      case LONG:
-        field = new LegacyLongField(type.name(), 0l, ft);
-        break;
-      case DOUBLE:
-        field = new LegacyDoubleField(type.name(), 0.0, ft);
-        break;
-      default:
-        fail();
-        field = null;
-      }
-      numericFieldMap.put(type.name(), field);
-      doc.add(field);
-    }
-    
-    numericConfigMap.put(DATE_FIELD_NAME, new NumericConfig(PRECISION_STEP,
-        DATE_FORMAT, LegacyNumericType.LONG));
-    FieldType ft = new FieldType(LegacyLongField.TYPE_NOT_STORED);
-    ft.setStored(true);
-    ft.setNumericPrecisionStep(PRECISION_STEP);
-    LegacyLongField dateField = new LegacyLongField(DATE_FIELD_NAME, 0l, ft);
-    numericFieldMap.put(DATE_FIELD_NAME, dateField);
-    doc.add(dateField);
-    
-    for (NumberType numberType : NumberType.values()) {
-      setFieldValues(numberType, numericFieldMap);
-      if (VERBOSE) System.out.println("Indexing document: " + doc);
-      writer.addDocument(doc);
-    }
-    
-    reader = writer.getReader();
-    searcher = newSearcher(reader);
-    writer.close();
-    
-  }
-  
-  private static Number getNumberType(NumberType numberType, String fieldName) {
-    
-    if (numberType == null) {
-      return null;
-    }
-    
-    switch (numberType) {
-      
-      case POSITIVE:
-        return RANDOM_NUMBER_MAP.get(fieldName);
-        
-      case NEGATIVE:
-        Number number = RANDOM_NUMBER_MAP.get(fieldName);
-        
-        if (LegacyNumericType.LONG.name().equals(fieldName)
-            || DATE_FIELD_NAME.equals(fieldName)) {
-          number = -number.longValue();
-          
-        } else if (FieldType.LegacyNumericType.DOUBLE.name().equals(fieldName)) {
-          number = -number.doubleValue();
-          
-        } else if (FieldType.LegacyNumericType.FLOAT.name().equals(fieldName)) {
-          number = -number.floatValue();
-          
-        } else if (LegacyNumericType.INT.name().equals(fieldName)) {
-          number = -number.intValue();
-          
-        } else {
-          throw new IllegalArgumentException("field name not found: "
-              + fieldName);
-        }
-        
-        return number;
-        
-      default:
-        return 0;
-        
-    }
-    
-  }
-  
-  private static void setFieldValues(NumberType numberType,
-      HashMap<String,Field> numericFieldMap) {
-    
-    Number number = getNumberType(numberType, LegacyNumericType.DOUBLE
-        .name());
-    numericFieldMap.get(LegacyNumericType.DOUBLE.name()).setDoubleValue(
-        number.doubleValue());
-    
-    number = getNumberType(numberType, FieldType.LegacyNumericType.INT.name());
-    numericFieldMap.get(FieldType.LegacyNumericType.INT.name()).setIntValue(
-        number.intValue());
-    
-    number = getNumberType(numberType, LegacyNumericType.LONG.name());
-    numericFieldMap.get(FieldType.LegacyNumericType.LONG.name()).setLongValue(
-        number.longValue());
-    
-    number = getNumberType(numberType, FieldType.LegacyNumericType.FLOAT.name());
-    numericFieldMap.get(FieldType.LegacyNumericType.FLOAT.name()).setFloatValue(
-        number.floatValue());
-    
-    number = getNumberType(numberType, DATE_FIELD_NAME);
-    numericFieldMap.get(DATE_FIELD_NAME).setLongValue(number.longValue());
-  }
-  
-  private static int randomDateStyle(Random random) {
-    return DATE_STYLES[random.nextInt(DATE_STYLES.length)];
-  }
-  
-  @Test
-  public void testInclusiveNumericRange() throws Exception {
-    assertRangeQuery(NumberType.ZERO, NumberType.ZERO, true, true, 1);
-    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, true, 2);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, true, 2);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, true, 3);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, true, 1);
-  }
-  
-   @Test
-  // test disabled since standard syntax parser does not work with inclusive and
-  // exclusive at the same time
-  public void testInclusiveLowerNumericRange() throws Exception {
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, true, 1);
-    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, true, 1);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, true, 2);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, true, 0);
-   }
-  
-  @Test
-  // test disabled since standard syntax parser does not work with inclusive and
-  // exclusive at the same time
-  public void testInclusiveUpperNumericRange() throws Exception {
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, false, 1);
-    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, false, 1);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, false, 2);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, false, 0);
-  }
-  
-  @Test
-  public void testExclusiveNumericRange() throws Exception {
-    assertRangeQuery(NumberType.ZERO, NumberType.ZERO, false, false, 0);
-    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, false, 0);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, false, 0);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, false, 1);
-    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, false, 0);
-  }
-  
-  @Test
-  public void testOpenRangeNumericQuery() throws Exception {
-    assertOpenRangeQuery(NumberType.ZERO, "<", 1);
-    assertOpenRangeQuery(NumberType.POSITIVE, "<", 2);
-    assertOpenRangeQuery(NumberType.NEGATIVE, "<", 0);
-    
-    assertOpenRangeQuery(NumberType.ZERO, "<=", 2);
-    assertOpenRangeQuery(NumberType.POSITIVE, "<=", 3);
-    assertOpenRangeQuery(NumberType.NEGATIVE, "<=", 1);
-    
-    assertOpenRangeQuery(NumberType.ZERO, ">", 1);
-    assertOpenRangeQuery(NumberType.POSITIVE, ">", 0);
-    assertOpenRangeQuery(NumberType.NEGATIVE, ">", 2);
-    
-    assertOpenRangeQuery(NumberType.ZERO, ">=", 2);
-    assertOpenRangeQuery(NumberType.POSITIVE, ">=", 1);
-    assertOpenRangeQuery(NumberType.NEGATIVE, ">=", 3);
-    
-    assertOpenRangeQuery(NumberType.NEGATIVE, "=", 1);
-    assertOpenRangeQuery(NumberType.ZERO, "=", 1);
-    assertOpenRangeQuery(NumberType.POSITIVE, "=", 1);
-    
-    assertRangeQuery(NumberType.NEGATIVE, null, true, true, 3);
-    assertRangeQuery(NumberType.NEGATIVE, null, false, true, 2);
-    assertRangeQuery(NumberType.POSITIVE, null, true, false, 1);
-    assertRangeQuery(NumberType.ZERO, null, false, false, 1);
-
-    assertRangeQuery(null, NumberType.POSITIVE, true, true, 3);
-    assertRangeQuery(null, NumberType.POSITIVE, true, false, 2);
-    assertRangeQuery(null, NumberType.NEGATIVE, false, true, 1);
-    assertRangeQuery(null, NumberType.ZERO, false, false, 1);
-    
-    assertRangeQuery(null, null, false, false, 3);
-    assertRangeQuery(null, null, true, true, 3);
-    
-  }
-  
-  @Test
-  public void testSimpleNumericQuery() throws Exception {
-    assertSimpleQuery(NumberType.ZERO, 1);
-    assertSimpleQuery(NumberType.POSITIVE, 1);
-    assertSimpleQuery(NumberType.NEGATIVE, 1);
-  }
-  
-  public void assertRangeQuery(NumberType lowerType, NumberType upperType,
-      boolean lowerInclusive, boolean upperInclusive, int expectedDocCount)
-      throws QueryNodeException, IOException {
-    
-    StringBuilder sb = new StringBuilder();
-    
-    String lowerInclusiveStr = (lowerInclusive ? "[" : "{");
-    String upperInclusiveStr = (upperInclusive ? "]" : "}");
-    
-    for (LegacyNumericType type : LegacyNumericType.values()) {
-      String lowerStr = numberToString(getNumberType(lowerType, type.name()));
-      String upperStr = numberToString(getNumberType(upperType, type.name()));
-      
-      sb.append("+").append(type.name()).append(':').append(lowerInclusiveStr)
-          .append('"').append(lowerStr).append("\" TO \"").append(upperStr)
-          .append('"').append(upperInclusiveStr).append(' ');
-    }
-    
-    Number lowerDateNumber = getNumberType(lowerType, DATE_FIELD_NAME);
-    Number upperDateNumber = getNumberType(upperType, DATE_FIELD_NAME);
-    String lowerDateStr;
-    String upperDateStr;
-    
-    if (lowerDateNumber != null) {
-      lowerDateStr = ESCAPER.escape(
-          DATE_FORMAT.format(new Date(lowerDateNumber.longValue())), LOCALE,
-          EscapeQuerySyntax.Type.STRING).toString();
-      
-    } else {
-      lowerDateStr = "*";
-    }
-    
-    if (upperDateNumber != null) {
-    upperDateStr = ESCAPER.escape(
-          DATE_FORMAT.format(new Date(upperDateNumber.longValue())), LOCALE,
-          EscapeQuerySyntax.Type.STRING).toString();
-    
-    } else {
-      upperDateStr = "*";
-    }
-    
-    sb.append("+").append(DATE_FIELD_NAME).append(':')
-        .append(lowerInclusiveStr).append('"').append(lowerDateStr).append(
-            "\" TO \"").append(upperDateStr).append('"').append(
-            upperInclusiveStr);
-    
-    testQuery(sb.toString(), expectedDocCount);
-    
-  }
-  
-  public void assertOpenRangeQuery(NumberType boundType, String operator, int expectedDocCount)
-      throws QueryNodeException, IOException {
-
-    StringBuilder sb = new StringBuilder();
-    
-    for (LegacyNumericType type : FieldType.LegacyNumericType.values()) {
-      String boundStr = numberToString(getNumberType(boundType, type.name()));
-      
-      sb.append("+").append(type.name()).append(operator).append('"').append(boundStr).append('"').append(' ');
-    }
-    
-    String boundDateStr = ESCAPER.escape(
-        DATE_FORMAT.format(new Date(getNumberType(boundType, DATE_FIELD_NAME)
-            .longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
-    
-    sb.append("+").append(DATE_FIELD_NAME).append(operator).append('"').append(boundDateStr).append('"');
-    
-    testQuery(sb.toString(), expectedDocCount);
-  }
-  
-  public void assertSimpleQuery(NumberType numberType, int expectedDocCount)
-      throws QueryNodeException, IOException {
-    StringBuilder sb = new StringBuilder();
-    
-    for (LegacyNumericType type : LegacyNumericType.values()) {
-      String numberStr = numberToString(getNumberType(numberType, type.name()));
-      sb.append('+').append(type.name()).append(":\"").append(numberStr)
-          .append("\" ");
-    }
-    
-    String dateStr = ESCAPER.escape(
-        DATE_FORMAT.format(new Date(getNumberType(numberType, DATE_FIELD_NAME)
-            .longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
-    
-    sb.append('+').append(DATE_FIELD_NAME).append(":\"").append(dateStr)
-        .append('"');
-    
-    testQuery(sb.toString(), expectedDocCount);
-    
-  }
-  
-  private void testQuery(String queryStr, int expectedDocCount)
-      throws QueryNodeException, IOException {
-    if (VERBOSE) System.out.println("Parsing: " + queryStr);
-    
-    Query query = qp.parse(queryStr, FIELD_NAME);
-    if (VERBOSE) System.out.println("Querying: " + query);
-    TopDocs topDocs = searcher.search(query, 1000);
-    
-    String msg = "Query <" + queryStr + "> retrieved " + topDocs.totalHits
-        + " document(s), " + expectedDocCount + " document(s) expected.";
-    
-    if (VERBOSE) System.out.println(msg);
-    
-    assertEquals(msg, expectedDocCount, topDocs.totalHits);
-  }
-  
-  private static String numberToString(Number number) {
-    return number == null ? "*" : ESCAPER.escape(NUMBER_FORMAT.format(number),
-        LOCALE, EscapeQuerySyntax.Type.STRING).toString();
-  }
-  
-  private static Number normalizeNumber(Number number) throws ParseException {
-    return NUMBER_FORMAT.parse(NUMBER_FORMAT.format(number));
-  }
-  
-  @AfterClass
-  public static void afterClass() throws Exception {
-    searcher = null;
-    reader.close();
-    reader = null;
-    directory.close();
-    directory = null;
-    qp = null;
-    LOCALE = null;
-    TIMEZONE = null;
-    NUMBER_FORMAT = null;
-    DATE_FORMAT = null;
-    ESCAPER = null;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestPointQueryParser.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestPointQueryParser.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestPointQueryParser.java
new file mode 100644
index 0000000..323b0ff
--- /dev/null
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestPointQueryParser.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard;
+
+import java.text.NumberFormat;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.LongPoint;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+import org.apache.lucene.util.LuceneTestCase;
+
+/** Simple test for point field integration into the flexible QP */
+public class TestPointQueryParser extends LuceneTestCase {
+  
+  public void testIntegers() throws Exception {
+    StandardQueryParser parser = new StandardQueryParser();
+    Map<String,PointsConfig> pointsConfig = new HashMap<>();
+    pointsConfig.put("intField", new PointsConfig(NumberFormat.getIntegerInstance(Locale.ROOT), Integer.class));
+    parser.setPointsConfigMap(pointsConfig);
+    
+    assertEquals(IntPoint.newRangeQuery("intField", 1, 3),
+                 parser.parse("intField:[1 TO 3]", "body"));
+    assertEquals(IntPoint.newRangeQuery("intField", 1, 1),
+                 parser.parse("intField:1", "body"));
+  }
+  
+  public void testLongs() throws Exception {
+    StandardQueryParser parser = new StandardQueryParser();
+    Map<String,PointsConfig> pointsConfig = new HashMap<>();
+    pointsConfig.put("longField", new PointsConfig(NumberFormat.getIntegerInstance(Locale.ROOT), Long.class));
+    parser.setPointsConfigMap(pointsConfig);
+    
+    assertEquals(LongPoint.newRangeQuery("longField", 1, 3),
+                 parser.parse("longField:[1 TO 3]", "body"));
+    assertEquals(LongPoint.newRangeQuery("longField", 1, 1),
+                 parser.parse("longField:1", "body"));
+  }
+  
+  public void testFloats() throws Exception {
+    StandardQueryParser parser = new StandardQueryParser();
+    Map<String,PointsConfig> pointsConfig = new HashMap<>();
+    pointsConfig.put("floatField", new PointsConfig(NumberFormat.getNumberInstance(Locale.ROOT), Float.class));
+    parser.setPointsConfigMap(pointsConfig);
+    
+    assertEquals(FloatPoint.newRangeQuery("floatField", 1.5F, 3.6F),
+                 parser.parse("floatField:[1.5 TO 3.6]", "body"));
+    assertEquals(FloatPoint.newRangeQuery("floatField", 1.5F, 1.5F),
+                 parser.parse("floatField:1.5", "body"));
+  }
+  
+  public void testDoubles() throws Exception {
+    StandardQueryParser parser = new StandardQueryParser();
+    Map<String,PointsConfig> pointsConfig = new HashMap<>();
+    pointsConfig.put("doubleField", new PointsConfig(NumberFormat.getNumberInstance(Locale.ROOT), Double.class));
+    parser.setPointsConfigMap(pointsConfig);
+    
+    assertEquals(DoublePoint.newRangeQuery("doubleField", 1.5D, 3.6D),
+                 parser.parse("doubleField:[1.5 TO 3.6]", "body"));
+    assertEquals(DoublePoint.newRangeQuery("floatField", 1.5D, 1.5D),
+                 parser.parse("doubleField:1.5", "body"));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/tools/junit4/cached-timehints.txt
----------------------------------------------------------------------
diff --git a/lucene/tools/junit4/cached-timehints.txt b/lucene/tools/junit4/cached-timehints.txt
index 9c8b22a..f2b8974 100644
--- a/lucene/tools/junit4/cached-timehints.txt
+++ b/lucene/tools/junit4/cached-timehints.txt
@@ -548,7 +548,7 @@ org.apache.lucene.queryparser.flexible.spans.TestSpanQueryParser=711,339,113,55,
 org.apache.lucene.queryparser.flexible.spans.TestSpanQueryParserSimpleSample=51,644,92,32,129,60,21
 org.apache.lucene.queryparser.flexible.standard.TestMultiAnalyzerQPHelper=44,84,87,34,260,35,229
 org.apache.lucene.queryparser.flexible.standard.TestMultiFieldQPHelper=1152,1779,1888,384,179,1665,445
-org.apache.lucene.queryparser.flexible.standard.TestNumericQueryParser=344,496,451,1373,733,1420,367
+org.apache.lucene.queryparser.flexible.standard.TestLegacyNumericQueryParser=344,496,451,1373,733,1420,367
 org.apache.lucene.queryparser.flexible.standard.TestQPHelper=287,676,989,2137,860,586,612
 org.apache.lucene.queryparser.flexible.standard.TestStandardQP=1643,430,2182,2193,600,1506,741
 org.apache.lucene.queryparser.surround.query.SrndQueryTest=1062,92,92,212,65,95,113


[3/3] lucene-solr git commit: LUCENE-7089, LUCENE-7075: add points to flexible queryparser to replace legacy numerics support

Posted by rm...@apache.org.
LUCENE-7089, LUCENE-7075: add points to flexible queryparser to replace legacy numerics support


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/89cc676f
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/89cc676f
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/89cc676f

Branch: refs/heads/master
Commit: 89cc676f2bf560091bd24db544faa16946654164
Parents: f24810b
Author: Robert Muir <rm...@apache.org>
Authored: Wed Mar 9 21:05:26 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Wed Mar 9 21:06:41 2016 -0500

----------------------------------------------------------------------
 .../flexible/core/nodes/package-info.java       |   4 +-
 .../flexible/standard/StandardQueryParser.java  |  29 +-
 .../LegacyNumericRangeQueryNodeBuilder.java     |  93 ++++
 .../builders/NumericRangeQueryNodeBuilder.java  |  91 ----
 .../builders/PointRangeQueryNodeBuilder.java    | 137 +++++
 .../builders/StandardQueryTreeBuilder.java      |  12 +-
 .../standard/config/LegacyNumericConfig.java    | 166 ++++++
 .../LegacyNumericFieldConfigListener.java       |  75 +++
 .../flexible/standard/config/NumericConfig.java | 164 ------
 .../config/NumericFieldConfigListener.java      |  73 ---
 .../flexible/standard/config/PointsConfig.java  | 124 +++++
 .../standard/config/PointsConfigListener.java   |  65 +++
 .../config/StandardQueryConfigHandler.java      |  39 +-
 .../standard/nodes/LegacyNumericQueryNode.java  | 153 ++++++
 .../nodes/LegacyNumericRangeQueryNode.java      | 153 ++++++
 .../standard/nodes/NumericQueryNode.java        | 151 ------
 .../standard/nodes/NumericRangeQueryNode.java   | 151 ------
 .../flexible/standard/nodes/PointQueryNode.java | 151 ++++++
 .../standard/nodes/PointRangeQueryNode.java     | 124 +++++
 .../LegacyNumericQueryNodeProcessor.java        | 154 ++++++
 .../LegacyNumericRangeQueryNodeProcessor.java   | 170 ++++++
 .../processors/NumericQueryNodeProcessor.java   | 152 ------
 .../NumericRangeQueryNodeProcessor.java         | 168 ------
 .../processors/PointQueryNodeProcessor.java     | 136 +++++
 .../PointRangeQueryNodeProcessor.java           | 148 +++++
 .../StandardQueryNodeProcessorPipeline.java     |   6 +-
 .../standard/TestLegacyNumericQueryParser.java  | 535 +++++++++++++++++++
 .../standard/TestNumericQueryParser.java        | 535 -------------------
 .../flexible/standard/TestPointQueryParser.java |  82 +++
 lucene/tools/junit4/cached-timehints.txt        |   2 +-
 30 files changed, 2535 insertions(+), 1508 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/core/nodes/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/core/nodes/package-info.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/core/nodes/package-info.java
index c9d55ea..23c72a1 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/core/nodes/package-info.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/core/nodes/package-info.java
@@ -52,14 +52,14 @@
  * <li>FuzzyQueryNode - fuzzy node</li>
  * <li>TermRangeQueryNode - used for parametric field:[low_value TO high_value]</li>
  * <li>ProximityQueryNode - used for proximity search</li>
- * <li>NumericRangeQueryNode - used for numeric range search</li>
+ * <li>LegacyNumericRangeQueryNode - used for numeric range search</li>
  * <li>TokenizedPhraseQueryNode - used by tokenizers/lemmatizers/analyzers for phrases/autophrases</li>
  * </ul>
  * <p>
  * Leaf Nodes:
  * <ul>
  * <li>FieldQueryNode - field/value node</li>
- * <li>NumericQueryNode - used for numeric search</li>
+ * <li>LegacyNumericQueryNode - used for numeric search</li>
  * <li>PathQueryNode - {@link org.apache.lucene.queryparser.flexible.core.nodes.QueryNode} object used with path-like queries</li>
  * <li>OpaqueQueryNode - Used as for part of the query that can be parsed by other parsers. schema/value</li> 
  * <li>PrefixWildcardQueryNode - non-phrase wildcard query</li>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.java
index ada65a4..2774cf0 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/StandardQueryParser.java
@@ -29,7 +29,8 @@ import org.apache.lucene.queryparser.flexible.core.QueryParserHelper;
 import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
 import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryTreeBuilder;
 import org.apache.lucene.queryparser.flexible.standard.config.FuzzyConfig;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
 import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler;
 import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
 import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.Operator;
@@ -322,12 +323,30 @@ public class StandardQueryParser extends QueryParserHelper implements CommonQuer
     
   }
   
-  public void setNumericConfigMap(Map<String,NumericConfig> numericConfigMap) {
-    getQueryConfigHandler().set(ConfigurationKeys.NUMERIC_CONFIG_MAP, numericConfigMap);
+  /**
+   * Sets field configuration for legacy numeric fields
+   * @deprecated Index with points instead and use {@link #setPointsConfigMap(Map)}
+   */
+  @Deprecated
+  public void setLegacyNumericConfigMap(Map<String,LegacyNumericConfig> legacyNumericConfigMap) {
+    getQueryConfigHandler().set(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP, legacyNumericConfigMap);
+  }
+  
+  /**
+   * Gets field configuration for legacy numeric fields
+   * @deprecated Index with points instead and use {@link #getPointsConfigMap()}
+   */
+  @Deprecated
+  public Map<String,LegacyNumericConfig> getLegacyNumericConfigMap() {
+    return getQueryConfigHandler().get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP);
+  }
+  
+  public void setPointsConfigMap(Map<String,PointsConfig> pointsConfigMap) {
+    getQueryConfigHandler().set(ConfigurationKeys.POINTS_CONFIG_MAP, pointsConfigMap);
   }
   
-  public Map<String,NumericConfig> getNumericConfigMap() {
-    return getQueryConfigHandler().get(ConfigurationKeys.NUMERIC_CONFIG_MAP);
+  public Map<String,PointsConfig> getPointsConfigMap() {
+    return getQueryConfigHandler().get(ConfigurationKeys.POINTS_CONFIG_MAP);
   }
   
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/LegacyNumericRangeQueryNodeBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/LegacyNumericRangeQueryNodeBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/LegacyNumericRangeQueryNodeBuilder.java
new file mode 100644
index 0000000..8ae7d5e
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/LegacyNumericRangeQueryNodeBuilder.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.builders;
+
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
+import org.apache.lucene.search.LegacyNumericRangeQuery;
+
+/**
+ * Builds {@link org.apache.lucene.search.LegacyNumericRangeQuery}s out of {@link LegacyNumericRangeQueryNode}s.
+ *
+ * @see org.apache.lucene.search.LegacyNumericRangeQuery
+ * @see LegacyNumericRangeQueryNode
+ * @deprecated Index with points and use {@link PointRangeQueryNodeBuilder} instead.
+ */
+@Deprecated
+public class LegacyNumericRangeQueryNodeBuilder implements StandardQueryBuilder {
+  
+  /**
+   * Constructs a {@link LegacyNumericRangeQueryNodeBuilder} object.
+   */
+  public LegacyNumericRangeQueryNodeBuilder() {
+  // empty constructor
+  }
+  
+  @Override
+  public LegacyNumericRangeQuery<? extends Number> build(QueryNode queryNode)
+      throws QueryNodeException {
+    LegacyNumericRangeQueryNode numericRangeNode = (LegacyNumericRangeQueryNode) queryNode;
+    
+    LegacyNumericQueryNode lowerNumericNode = numericRangeNode.getLowerBound();
+    LegacyNumericQueryNode upperNumericNode = numericRangeNode.getUpperBound();
+    
+    Number lowerNumber = lowerNumericNode.getValue();
+    Number upperNumber = upperNumericNode.getValue();
+    
+    LegacyNumericConfig numericConfig = numericRangeNode.getNumericConfig();
+    FieldType.LegacyNumericType numberType = numericConfig.getType();
+    String field = StringUtils.toString(numericRangeNode.getField());
+    boolean minInclusive = numericRangeNode.isLowerInclusive();
+    boolean maxInclusive = numericRangeNode.isUpperInclusive();
+    int precisionStep = numericConfig.getPrecisionStep();
+    
+    switch (numberType) {
+      
+      case LONG:
+        return LegacyNumericRangeQuery.newLongRange(field, precisionStep,
+            (Long) lowerNumber, (Long) upperNumber, minInclusive, maxInclusive);
+      
+      case INT:
+        return LegacyNumericRangeQuery.newIntRange(field, precisionStep,
+            (Integer) lowerNumber, (Integer) upperNumber, minInclusive,
+            maxInclusive);
+      
+      case FLOAT:
+        return LegacyNumericRangeQuery.newFloatRange(field, precisionStep,
+            (Float) lowerNumber, (Float) upperNumber, minInclusive,
+            maxInclusive);
+      
+      case DOUBLE:
+        return LegacyNumericRangeQuery.newDoubleRange(field, precisionStep,
+            (Double) lowerNumber, (Double) upperNumber, minInclusive,
+            maxInclusive);
+        
+        default :
+          throw new QueryNodeException(new MessageImpl(
+            QueryParserMessages.UNSUPPORTED_NUMERIC_DATA_TYPE, numberType));
+        
+    }
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/NumericRangeQueryNodeBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/NumericRangeQueryNodeBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/NumericRangeQueryNodeBuilder.java
deleted file mode 100644
index 6c8790f..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/NumericRangeQueryNodeBuilder.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.builders;
-
-import org.apache.lucene.document.FieldType;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
-import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
-import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
-import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
-import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericRangeQueryNode;
-import org.apache.lucene.search.LegacyNumericRangeQuery;
-
-/**
- * Builds {@link org.apache.lucene.search.LegacyNumericRangeQuery}s out of {@link NumericRangeQueryNode}s.
- *
- * @see org.apache.lucene.search.LegacyNumericRangeQuery
- * @see NumericRangeQueryNode
- */
-public class NumericRangeQueryNodeBuilder implements StandardQueryBuilder {
-  
-  /**
-   * Constructs a {@link NumericRangeQueryNodeBuilder} object.
-   */
-  public NumericRangeQueryNodeBuilder() {
-  // empty constructor
-  }
-  
-  @Override
-  public LegacyNumericRangeQuery<? extends Number> build(QueryNode queryNode)
-      throws QueryNodeException {
-    NumericRangeQueryNode numericRangeNode = (NumericRangeQueryNode) queryNode;
-    
-    NumericQueryNode lowerNumericNode = numericRangeNode.getLowerBound();
-    NumericQueryNode upperNumericNode = numericRangeNode.getUpperBound();
-    
-    Number lowerNumber = lowerNumericNode.getValue();
-    Number upperNumber = upperNumericNode.getValue();
-    
-    NumericConfig numericConfig = numericRangeNode.getNumericConfig();
-    FieldType.LegacyNumericType numberType = numericConfig.getType();
-    String field = StringUtils.toString(numericRangeNode.getField());
-    boolean minInclusive = numericRangeNode.isLowerInclusive();
-    boolean maxInclusive = numericRangeNode.isUpperInclusive();
-    int precisionStep = numericConfig.getPrecisionStep();
-    
-    switch (numberType) {
-      
-      case LONG:
-        return LegacyNumericRangeQuery.newLongRange(field, precisionStep,
-            (Long) lowerNumber, (Long) upperNumber, minInclusive, maxInclusive);
-      
-      case INT:
-        return LegacyNumericRangeQuery.newIntRange(field, precisionStep,
-            (Integer) lowerNumber, (Integer) upperNumber, minInclusive,
-            maxInclusive);
-      
-      case FLOAT:
-        return LegacyNumericRangeQuery.newFloatRange(field, precisionStep,
-            (Float) lowerNumber, (Float) upperNumber, minInclusive,
-            maxInclusive);
-      
-      case DOUBLE:
-        return LegacyNumericRangeQuery.newDoubleRange(field, precisionStep,
-            (Double) lowerNumber, (Double) upperNumber, minInclusive,
-            maxInclusive);
-        
-        default :
-          throw new QueryNodeException(new MessageImpl(
-            QueryParserMessages.UNSUPPORTED_NUMERIC_DATA_TYPE, numberType));
-        
-    }
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PointRangeQueryNodeBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PointRangeQueryNodeBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PointRangeQueryNodeBuilder.java
new file mode 100644
index 0000000..0cce4bf
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/PointRangeQueryNodeBuilder.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.builders;
+
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.LongPoint;
+import org.apache.lucene.index.PointValues;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointRangeQueryNode;
+import org.apache.lucene.search.Query;
+
+/**
+ * Builds {@link PointValues} range queries out of {@link PointRangeQueryNode}s.
+ *
+ * @see PointRangeQueryNode
+ */
+public class PointRangeQueryNodeBuilder implements StandardQueryBuilder {
+  
+  /**
+   * Constructs a {@link PointRangeQueryNodeBuilder} object.
+   */
+  public PointRangeQueryNodeBuilder() {
+  // empty constructor
+  }
+  
+  @Override
+  public Query build(QueryNode queryNode) throws QueryNodeException {
+    PointRangeQueryNode numericRangeNode = (PointRangeQueryNode) queryNode;
+    
+    PointQueryNode lowerNumericNode = numericRangeNode.getLowerBound();
+    PointQueryNode upperNumericNode = numericRangeNode.getUpperBound();
+    
+    Number lowerNumber = lowerNumericNode.getValue();
+    Number upperNumber = upperNumericNode.getValue();
+    
+    PointsConfig pointsConfig = numericRangeNode.getPointsConfig();
+    Class<? extends Number> numberType = pointsConfig.getType();
+    String field = StringUtils.toString(numericRangeNode.getField());
+    boolean minInclusive = numericRangeNode.isLowerInclusive();
+    boolean maxInclusive = numericRangeNode.isUpperInclusive();
+    
+    // TODO: push down cleaning up of crazy nulls and inclusive/exclusive elsewhere
+    if (Integer.class.equals(numberType)) {
+      Integer lower = (Integer) lowerNumber;
+      if (lower == null) {
+        lower = Integer.MIN_VALUE;
+      }
+      if (minInclusive == false) {
+        lower = lower + 1;
+      }
+      
+      Integer upper = (Integer) upperNumber;
+      if (upper == null) {
+        upper = Integer.MAX_VALUE;
+      }
+      if (maxInclusive == false) {
+        upper = upper - 1;
+      }
+      return IntPoint.newRangeQuery(field, lower, upper);
+    } else if (Long.class.equals(numberType)) {
+      Long lower = (Long) lowerNumber;
+      if (lower == null) {
+        lower = Long.MIN_VALUE;
+      }
+      if (minInclusive == false) {
+        lower = lower + 1;
+      }
+      
+      Long upper = (Long) upperNumber;
+      if (upper == null) {
+        upper = Long.MAX_VALUE;
+      }
+      if (maxInclusive == false) {
+        upper = upper - 1;
+      }
+      return LongPoint.newRangeQuery(field, lower, upper);
+    } else if (Float.class.equals(numberType)) {
+      Float lower = (Float) lowerNumber;
+      if (lower == null) {
+        lower = Float.NEGATIVE_INFINITY;
+      }
+      if (minInclusive == false) {
+        lower = Math.nextUp(lower);
+      }
+      
+      Float upper = (Float) upperNumber;
+      if (upper == null) {
+        upper = Float.POSITIVE_INFINITY;
+      }
+      if (maxInclusive == false) {
+        upper = Math.nextDown(upper);
+      }
+      return FloatPoint.newRangeQuery(field, lower, upper);
+    } else if (Double.class.equals(numberType)) {
+      Double lower = (Double) lowerNumber;
+      if (lower == null) {
+        lower = Double.NEGATIVE_INFINITY;
+      }
+      if (minInclusive == false) {
+        lower = Math.nextUp(lower);
+      }
+      
+      Double upper = (Double) upperNumber;
+      if (upper == null) {
+        upper = Double.POSITIVE_INFINITY;
+      }
+      if (maxInclusive == false) {
+        upper = Math.nextDown(upper);
+      }
+      return DoublePoint.newRangeQuery(field, lower, upper);
+    } else {
+      throw new QueryNodeException(new MessageImpl(QueryParserMessages.UNSUPPORTED_NUMERIC_DATA_TYPE, numberType));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardQueryTreeBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardQueryTreeBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardQueryTreeBuilder.java
index 2d7c643..360f6a7 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardQueryTreeBuilder.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardQueryTreeBuilder.java
@@ -30,8 +30,10 @@ import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
 import org.apache.lucene.queryparser.flexible.core.nodes.SlopQueryNode;
 import org.apache.lucene.queryparser.flexible.core.nodes.TokenizedPhraseQueryNode;
 import org.apache.lucene.queryparser.flexible.standard.nodes.MultiPhraseQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericRangeQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointRangeQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
 import org.apache.lucene.queryparser.flexible.standard.nodes.PrefixWildcardQueryNode;
 import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
 import org.apache.lucene.queryparser.flexible.standard.nodes.RegexpQueryNode;
@@ -57,8 +59,10 @@ public class StandardQueryTreeBuilder extends QueryTreeBuilder implements
     setBuilder(FieldQueryNode.class, new FieldQueryNodeBuilder());
     setBuilder(BooleanQueryNode.class, new BooleanQueryNodeBuilder());
     setBuilder(FuzzyQueryNode.class, new FuzzyQueryNodeBuilder());
-    setBuilder(NumericQueryNode.class, new DummyQueryNodeBuilder());
-    setBuilder(NumericRangeQueryNode.class, new NumericRangeQueryNodeBuilder());
+    setBuilder(LegacyNumericQueryNode.class, new DummyQueryNodeBuilder());
+    setBuilder(LegacyNumericRangeQueryNode.class, new LegacyNumericRangeQueryNodeBuilder());
+    setBuilder(PointQueryNode.class, new DummyQueryNodeBuilder());
+    setBuilder(PointRangeQueryNode.class, new PointRangeQueryNodeBuilder());
     setBuilder(BoostQueryNode.class, new BoostQueryNodeBuilder());
     setBuilder(ModifierQueryNode.class, new ModifierQueryNodeBuilder());
     setBuilder(WildcardQueryNode.class, new WildcardQueryNodeBuilder());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericConfig.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericConfig.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericConfig.java
new file mode 100644
index 0000000..985f55a
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericConfig.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.config;
+
+import java.text.NumberFormat;
+import java.util.Objects;
+
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.FieldType.LegacyNumericType;
+
+/**
+ * This class holds the configuration used to parse numeric queries and create
+ * {@link org.apache.lucene.search.LegacyNumericRangeQuery}s.
+ * 
+ * @see org.apache.lucene.search.LegacyNumericRangeQuery
+ * @see NumberFormat
+ * @deprecated Index with Points instead and use {@link PointsConfig}
+ */
+@Deprecated
+public class LegacyNumericConfig {
+  
+  private int precisionStep;
+  
+  private NumberFormat format;
+  
+  private FieldType.LegacyNumericType type;
+  
+  /**
+   * Constructs a {@link LegacyNumericConfig} object.
+   * 
+   * @param precisionStep
+   *          the precision used to index the numeric values
+   * @param format
+   *          the {@link NumberFormat} used to parse a {@link String} to
+   *          {@link Number}
+   * @param type
+   *          the numeric type used to index the numeric values
+   * 
+   * @see LegacyNumericConfig#setPrecisionStep(int)
+   * @see LegacyNumericConfig#setNumberFormat(NumberFormat)
+   * @see #setType(org.apache.lucene.document.FieldType.LegacyNumericType)
+   */
+  public LegacyNumericConfig(int precisionStep, NumberFormat format,
+      LegacyNumericType type) {
+    setPrecisionStep(precisionStep);
+    setNumberFormat(format);
+    setType(type);
+    
+  }
+  
+  /**
+   * Returns the precision used to index the numeric values
+   * 
+   * @return the precision used to index the numeric values
+   * 
+   * @see org.apache.lucene.search.LegacyNumericRangeQuery#getPrecisionStep()
+   */
+  public int getPrecisionStep() {
+    return precisionStep;
+  }
+  
+  /**
+   * Sets the precision used to index the numeric values
+   * 
+   * @param precisionStep
+   *          the precision used to index the numeric values
+   * 
+   * @see org.apache.lucene.search.LegacyNumericRangeQuery#getPrecisionStep()
+   */
+  public void setPrecisionStep(int precisionStep) {
+    this.precisionStep = precisionStep;
+  }
+  
+  /**
+   * Returns the {@link NumberFormat} used to parse a {@link String} to
+   * {@link Number}
+   * 
+   * @return the {@link NumberFormat} used to parse a {@link String} to
+   *         {@link Number}
+   */
+  public NumberFormat getNumberFormat() {
+    return format;
+  }
+  
+  /**
+   * Returns the numeric type used to index the numeric values
+   * 
+   * @return the numeric type used to index the numeric values
+   */
+  public LegacyNumericType getType() {
+    return type;
+  }
+  
+  /**
+   * Sets the numeric type used to index the numeric values
+   * 
+   * @param type the numeric type used to index the numeric values
+   */
+  public void setType(LegacyNumericType type) {
+    
+    if (type == null) {
+      throw new IllegalArgumentException("type cannot be null!");
+    }
+    
+    this.type = type;
+    
+  }
+  
+  /**
+   * Sets the {@link NumberFormat} used to parse a {@link String} to
+   * {@link Number}
+   * 
+   * @param format
+   *          the {@link NumberFormat} used to parse a {@link String} to
+   *          {@link Number}, cannot be <code>null</code>
+   */
+  public void setNumberFormat(NumberFormat format) {
+    
+    if (format == null) {
+      throw new IllegalArgumentException("format cannot be null!");
+    }
+    
+    this.format = format;
+    
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    
+    if (obj == this) return true;
+    
+    if (obj instanceof LegacyNumericConfig) {
+      LegacyNumericConfig other = (LegacyNumericConfig) obj;
+      
+      if (this.precisionStep == other.precisionStep
+          && this.type == other.type
+          && (this.format == other.format || (this.format.equals(other.format)))) {
+        return true;
+      }
+      
+    }
+    
+    return false;
+    
+  }
+  
+  @Override
+  public int hashCode() {
+    return Objects.hash(precisionStep, type, format);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericFieldConfigListener.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericFieldConfigListener.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericFieldConfigListener.java
new file mode 100644
index 0000000..f2d3124
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/LegacyNumericFieldConfigListener.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.config;
+
+import java.util.Map;
+
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfigListener;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+
+/**
+ * This listener is used to listen to {@link FieldConfig} requests in
+ * {@link QueryConfigHandler} and add {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG}
+ * based on the {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG_MAP} set in the
+ * {@link QueryConfigHandler}.
+ * 
+ * @see LegacyNumericConfig
+ * @see QueryConfigHandler
+ * @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
+ * @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG_MAP
+ * @deprecated Index with Points instead and use {@link PointsConfigListener}
+ */
+@Deprecated
+public class LegacyNumericFieldConfigListener implements FieldConfigListener {
+  
+  final private QueryConfigHandler config;
+  
+  /**
+   * Constructs a {@link LegacyNumericFieldConfigListener} object using the given {@link QueryConfigHandler}.
+   * 
+   * @param config the {@link QueryConfigHandler} it will listen too
+   */
+  public LegacyNumericFieldConfigListener(QueryConfigHandler config) {
+    
+    if (config == null) {
+      throw new IllegalArgumentException("config cannot be null!");
+    }
+    
+    this.config = config;
+    
+  }
+  
+  @Override
+  public void buildFieldConfig(FieldConfig fieldConfig) {
+    Map<String,LegacyNumericConfig> numericConfigMap = config
+        .get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP);
+    
+    if (numericConfigMap != null) {
+      LegacyNumericConfig numericConfig = numericConfigMap
+          .get(fieldConfig.getField());
+      
+      if (numericConfig != null) {
+        fieldConfig.set(ConfigurationKeys.LEGACY_NUMERIC_CONFIG, numericConfig);
+      }
+      
+    }
+    
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericConfig.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericConfig.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericConfig.java
deleted file mode 100644
index c457a4e..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericConfig.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.config;
-
-import java.text.NumberFormat;
-import java.util.Objects;
-
-import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
-
-/**
- * This class holds the configuration used to parse numeric queries and create
- * {@link org.apache.lucene.search.LegacyNumericRangeQuery}s.
- * 
- * @see org.apache.lucene.search.LegacyNumericRangeQuery
- * @see NumberFormat
- */
-public class NumericConfig {
-  
-  private int precisionStep;
-  
-  private NumberFormat format;
-  
-  private FieldType.LegacyNumericType type;
-  
-  /**
-   * Constructs a {@link NumericConfig} object.
-   * 
-   * @param precisionStep
-   *          the precision used to index the numeric values
-   * @param format
-   *          the {@link NumberFormat} used to parse a {@link String} to
-   *          {@link Number}
-   * @param type
-   *          the numeric type used to index the numeric values
-   * 
-   * @see NumericConfig#setPrecisionStep(int)
-   * @see NumericConfig#setNumberFormat(NumberFormat)
-   * @see #setType(org.apache.lucene.document.FieldType.LegacyNumericType)
-   */
-  public NumericConfig(int precisionStep, NumberFormat format,
-      LegacyNumericType type) {
-    setPrecisionStep(precisionStep);
-    setNumberFormat(format);
-    setType(type);
-    
-  }
-  
-  /**
-   * Returns the precision used to index the numeric values
-   * 
-   * @return the precision used to index the numeric values
-   * 
-   * @see org.apache.lucene.search.LegacyNumericRangeQuery#getPrecisionStep()
-   */
-  public int getPrecisionStep() {
-    return precisionStep;
-  }
-  
-  /**
-   * Sets the precision used to index the numeric values
-   * 
-   * @param precisionStep
-   *          the precision used to index the numeric values
-   * 
-   * @see org.apache.lucene.search.LegacyNumericRangeQuery#getPrecisionStep()
-   */
-  public void setPrecisionStep(int precisionStep) {
-    this.precisionStep = precisionStep;
-  }
-  
-  /**
-   * Returns the {@link NumberFormat} used to parse a {@link String} to
-   * {@link Number}
-   * 
-   * @return the {@link NumberFormat} used to parse a {@link String} to
-   *         {@link Number}
-   */
-  public NumberFormat getNumberFormat() {
-    return format;
-  }
-  
-  /**
-   * Returns the numeric type used to index the numeric values
-   * 
-   * @return the numeric type used to index the numeric values
-   */
-  public LegacyNumericType getType() {
-    return type;
-  }
-  
-  /**
-   * Sets the numeric type used to index the numeric values
-   * 
-   * @param type the numeric type used to index the numeric values
-   */
-  public void setType(LegacyNumericType type) {
-    
-    if (type == null) {
-      throw new IllegalArgumentException("type cannot be null!");
-    }
-    
-    this.type = type;
-    
-  }
-  
-  /**
-   * Sets the {@link NumberFormat} used to parse a {@link String} to
-   * {@link Number}
-   * 
-   * @param format
-   *          the {@link NumberFormat} used to parse a {@link String} to
-   *          {@link Number}, cannot be <code>null</code>
-   */
-  public void setNumberFormat(NumberFormat format) {
-    
-    if (format == null) {
-      throw new IllegalArgumentException("format cannot be null!");
-    }
-    
-    this.format = format;
-    
-  }
-  
-  @Override
-  public boolean equals(Object obj) {
-    
-    if (obj == this) return true;
-    
-    if (obj instanceof NumericConfig) {
-      NumericConfig other = (NumericConfig) obj;
-      
-      if (this.precisionStep == other.precisionStep
-          && this.type == other.type
-          && (this.format == other.format || (this.format.equals(other.format)))) {
-        return true;
-      }
-      
-    }
-    
-    return false;
-    
-  }
-  
-  @Override
-  public int hashCode() {
-    return Objects.hash(precisionStep, type, format);
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericFieldConfigListener.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericFieldConfigListener.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericFieldConfigListener.java
deleted file mode 100644
index c28cf2c..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/NumericFieldConfigListener.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.config;
-
-import java.util.Map;
-
-import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
-import org.apache.lucene.queryparser.flexible.core.config.FieldConfigListener;
-import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
-import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
-
-/**
- * This listener is used to listen to {@link FieldConfig} requests in
- * {@link QueryConfigHandler} and add {@link ConfigurationKeys#NUMERIC_CONFIG}
- * based on the {@link ConfigurationKeys#NUMERIC_CONFIG_MAP} set in the
- * {@link QueryConfigHandler}.
- * 
- * @see NumericConfig
- * @see QueryConfigHandler
- * @see ConfigurationKeys#NUMERIC_CONFIG
- * @see ConfigurationKeys#NUMERIC_CONFIG_MAP
- */
-public class NumericFieldConfigListener implements FieldConfigListener {
-  
-  final private QueryConfigHandler config;
-  
-  /**
-   * Construcs a {@link NumericFieldConfigListener} object using the given {@link QueryConfigHandler}.
-   * 
-   * @param config the {@link QueryConfigHandler} it will listen too
-   */
-  public NumericFieldConfigListener(QueryConfigHandler config) {
-    
-    if (config == null) {
-      throw new IllegalArgumentException("config cannot be null!");
-    }
-    
-    this.config = config;
-    
-  }
-  
-  @Override
-  public void buildFieldConfig(FieldConfig fieldConfig) {
-    Map<String,NumericConfig> numericConfigMap = config
-        .get(ConfigurationKeys.NUMERIC_CONFIG_MAP);
-    
-    if (numericConfigMap != null) {
-      NumericConfig numericConfig = numericConfigMap
-          .get(fieldConfig.getField());
-      
-      if (numericConfig != null) {
-        fieldConfig.set(ConfigurationKeys.NUMERIC_CONFIG, numericConfig);
-      }
-      
-    }
-    
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfig.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfig.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfig.java
new file mode 100644
index 0000000..db59b48
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfig.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.config;
+
+import java.text.NumberFormat;
+
+import org.apache.lucene.index.PointValues;
+
+/**
+ * This class holds the configuration used to parse numeric queries and create
+ * {@link PointValues} queries.
+ * 
+ * @see PointValues
+ * @see NumberFormat
+ */
+public class PointsConfig {
+    
+  private NumberFormat format;
+  
+  private Class<? extends Number> type;
+  
+  /**
+   * Constructs a {@link PointsConfig} object.
+   * 
+   * @param format
+   *          the {@link NumberFormat} used to parse a {@link String} to
+   *          {@link Number}
+   * @param type
+   *          the numeric type used to index the numeric values
+   * 
+   * @see PointsConfig#setNumberFormat(NumberFormat)
+   */
+  public PointsConfig(NumberFormat format, Class<? extends Number> type) {
+    setNumberFormat(format);
+    setType(type);    
+  }
+  
+  /**
+   * Returns the {@link NumberFormat} used to parse a {@link String} to
+   * {@link Number}
+   * 
+   * @return the {@link NumberFormat} used to parse a {@link String} to
+   *         {@link Number}
+   */
+  public NumberFormat getNumberFormat() {
+    return format;
+  }
+  
+  /**
+   * Returns the numeric type used to index the numeric values
+   * 
+   * @return the numeric type used to index the numeric values
+   */
+  public Class<? extends Number> getType() {
+    return type;
+  }
+  
+  /**
+   * Sets the numeric type used to index the numeric values
+   * 
+   * @param type the numeric type used to index the numeric values
+   */
+  public void setType(Class<? extends Number> type) {
+    if (type == null) {
+      throw new IllegalArgumentException("type cannot be null!");
+    }
+    if (Integer.class.equals(type) == false &&
+        Long.class.equals(type) == false &&
+        Float.class.equals(type) == false &&
+        Double.class.equals(type) == false) {
+      throw new IllegalArgumentException("unsupported numeric type: " + type);
+    }
+    this.type = type;
+  }
+  
+  /**
+   * Sets the {@link NumberFormat} used to parse a {@link String} to
+   * {@link Number}
+   * 
+   * @param format
+   *          the {@link NumberFormat} used to parse a {@link String} to
+   *          {@link Number}, cannot be <code>null</code>
+   */
+  public void setNumberFormat(NumberFormat format) {    
+    if (format == null) {
+      throw new IllegalArgumentException("format cannot be null!");
+    } 
+    this.format = format;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + format.hashCode();
+    result = prime * result + type.hashCode();
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) return true;
+    if (obj == null) return false;
+    if (getClass() != obj.getClass()) return false;
+    PointsConfig other = (PointsConfig) obj;
+    if (!format.equals(other.format)) return false;
+    if (!type.equals(other.type)) return false;
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfigListener.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfigListener.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfigListener.java
new file mode 100644
index 0000000..9efbbb7
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/PointsConfigListener.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.config;
+
+import java.util.Map;
+
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfigListener;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+
+/**
+ * This listener is used to listen to {@link FieldConfig} requests in
+ * {@link QueryConfigHandler} and add {@link ConfigurationKeys#POINTS_CONFIG}
+ * based on the {@link ConfigurationKeys#POINTS_CONFIG_MAP} set in the
+ * {@link QueryConfigHandler}.
+ * 
+ * @see PointsConfig
+ * @see QueryConfigHandler
+ * @see ConfigurationKeys#POINTS_CONFIG
+ * @see ConfigurationKeys#POINTS_CONFIG_MAP
+ */
+public class PointsConfigListener implements FieldConfigListener {
+  
+  final private QueryConfigHandler config;
+  
+  /**
+   * Constructs a {@link PointsConfigListener} object using the given {@link QueryConfigHandler}.
+   * 
+   * @param config the {@link QueryConfigHandler} it will listen too
+   */
+  public PointsConfigListener(QueryConfigHandler config) { 
+    if (config == null) {
+      throw new IllegalArgumentException("config cannot be null!");
+    }
+    this.config = config;
+  }
+  
+  @Override
+  public void buildFieldConfig(FieldConfig fieldConfig) {
+    Map<String,PointsConfig> pointsConfigMap = config.get(ConfigurationKeys.POINTS_CONFIG_MAP);
+    
+    if (pointsConfigMap != null) {
+      PointsConfig pointsConfig = pointsConfigMap.get(fieldConfig.getField());
+      
+      if (pointsConfig != null) {
+        fieldConfig.set(ConfigurationKeys.POINTS_CONFIG, pointsConfig);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/StandardQueryConfigHandler.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/StandardQueryConfigHandler.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/StandardQueryConfigHandler.java
index 77bd7bb..bba95ee 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/StandardQueryConfigHandler.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/config/StandardQueryConfigHandler.java
@@ -167,21 +167,41 @@ public class StandardQueryConfigHandler extends QueryConfigHandler {
     final public static ConfigurationKey<Float> BOOST = ConfigurationKey.newInstance();
     
     /**
-     * Key used to set a field to its {@link NumericConfig}.
+     * Key used to set a field to its {@link LegacyNumericConfig}.
      * 
-     * @see StandardQueryParser#setNumericConfigMap(Map)
-     * @see StandardQueryParser#getNumericConfigMap()
+     * @see StandardQueryParser#setLegacyNumericConfigMap(Map)
+     * @see StandardQueryParser#getLegacyNumericConfigMap()
+     * @deprecated Index with Points instead and use {@link #POINTS_CONFIG}
      */
-    final public static ConfigurationKey<NumericConfig> NUMERIC_CONFIG = ConfigurationKey.newInstance();
+    @Deprecated
+    final public static ConfigurationKey<LegacyNumericConfig> LEGACY_NUMERIC_CONFIG = ConfigurationKey.newInstance();
     
     /**
-     * Key used to set the {@link NumericConfig} in {@link FieldConfig} for numeric fields.
+     * Key used to set the {@link LegacyNumericConfig} in {@link FieldConfig} for numeric fields.
      * 
-     * @see StandardQueryParser#setNumericConfigMap(Map)
-     * @see StandardQueryParser#getNumericConfigMap()
+     * @see StandardQueryParser#setLegacyNumericConfigMap(Map)
+     * @see StandardQueryParser#getLegacyNumericConfigMap()
+     * @deprecated Index with Points instead and use {@link #POINTS_CONFIG_MAP}
      */
-    final public static ConfigurationKey<Map<String,NumericConfig>> NUMERIC_CONFIG_MAP = ConfigurationKey.newInstance();
+    @Deprecated
+    final public static ConfigurationKey<Map<String,LegacyNumericConfig>> LEGACY_NUMERIC_CONFIG_MAP = ConfigurationKey.newInstance();
     
+    /**
+     * Key used to set a field to its {@link PointsConfig}.
+     * 
+     * @see StandardQueryParser#setLegacyNumericConfigMap(Map)
+     * @see StandardQueryParser#getLegacyNumericConfigMap()
+     */
+    final public static ConfigurationKey<PointsConfig> POINTS_CONFIG = ConfigurationKey.newInstance();
+
+    /**
+     * Key used to set the {@link PointsConfig} in {@link FieldConfig} for point fields.
+     * 
+     * @see StandardQueryParser#setLegacyNumericConfigMap(Map)
+     * @see StandardQueryParser#getLegacyNumericConfigMap()
+     */
+    final public static ConfigurationKey<Map<String,PointsConfig>> POINTS_CONFIG_MAP = ConfigurationKey.newInstance();
+
   }
   
   /**
@@ -195,7 +215,8 @@ public class StandardQueryConfigHandler extends QueryConfigHandler {
     // Add listener that will build the FieldConfig.
     addFieldConfigListener(new FieldBoostMapFCListener(this));
     addFieldConfigListener(new FieldDateResolutionFCListener(this));
-    addFieldConfigListener(new NumericFieldConfigListener(this));
+    addFieldConfigListener(new LegacyNumericFieldConfigListener(this));
+    addFieldConfigListener(new PointsConfigListener(this));
     
     // Default Values
     set(ConfigurationKeys.ALLOW_LEADING_WILDCARD, false); // default in 2.9

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericQueryNode.java
new file mode 100644
index 0000000..b644d8a
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericQueryNode.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.nodes;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldValuePairQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax.Type;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+
+/**
+ * This query node represents a field query that holds a numeric value. It is
+ * similar to {@link FieldQueryNode}, however the {@link #getValue()} returns a
+ * {@link Number}.
+ * 
+ * @see LegacyNumericConfig
+ * @deprecated Index with Points instead and use {@link PointQueryNode} instead.
+ */
+@Deprecated
+public class LegacyNumericQueryNode extends QueryNodeImpl implements
+    FieldValuePairQueryNode<Number> {
+  
+  private NumberFormat numberFormat;
+  
+  private CharSequence field;
+  
+  private Number value;
+  
+  /**
+   * Creates a {@link LegacyNumericQueryNode} object using the given field,
+   * {@link Number} value and {@link NumberFormat} used to convert the value to
+   * {@link String}.
+   * 
+   * @param field the field associated with this query node
+   * @param value the value hold by this node
+   * @param numberFormat the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public LegacyNumericQueryNode(CharSequence field, Number value,
+      NumberFormat numberFormat) {
+    
+    super();
+    
+    setNumberFormat(numberFormat);
+    setField(field);
+    setValue(value);
+    
+  }
+  
+  /**
+   * Returns the field associated with this node.
+   * 
+   * @return the field associated with this node
+   */
+  @Override
+  public CharSequence getField() {
+    return this.field;
+  }
+  
+  /**
+   * Sets the field associated with this node.
+   * 
+   * @param fieldName the field associated with this node
+   */
+  @Override
+  public void setField(CharSequence fieldName) {
+    this.field = fieldName;
+  }
+  
+  /**
+   * This method is used to get the value converted to {@link String} and
+   * escaped using the given {@link EscapeQuerySyntax}.
+   * 
+   * @param escaper the {@link EscapeQuerySyntax} used to escape the value {@link String}
+   * 
+   * @return the value converte to {@link String} and escaped
+   */
+  protected CharSequence getTermEscaped(EscapeQuerySyntax escaper) {
+    return escaper.escape(numberFormat.format(this.value),
+        Locale.ROOT, Type.NORMAL);
+  }
+  
+  @Override
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (isDefaultField(this.field)) {
+      return getTermEscaped(escapeSyntaxParser);
+    } else {
+      return this.field + ":" + getTermEscaped(escapeSyntaxParser);
+    }
+  }
+  
+  /**
+   * Sets the {@link NumberFormat} used to convert the value to {@link String}.
+   * 
+   * @param format the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public void setNumberFormat(NumberFormat format) {
+    this.numberFormat = format;
+  }
+  
+  /**
+   * Returns the {@link NumberFormat} used to convert the value to {@link String}.
+   * 
+   * @return the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public NumberFormat getNumberFormat() {
+    return this.numberFormat;
+  }
+  
+  /**
+   * Returns the numeric value as {@link Number}.
+   * 
+   * @return the numeric value
+   */
+  @Override
+  public Number getValue() {
+    return value;
+  }
+  
+  /**
+   * Sets the numeric value.
+   * 
+   * @param value the numeric value
+   */
+  @Override
+  public void setValue(Number value) {
+    this.value = value;
+  }
+  
+  @Override
+  public String toString() {
+    return "<numeric field='" + this.field + "' number='"
+        + numberFormat.format(value) + "'/>";
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericRangeQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericRangeQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericRangeQueryNode.java
new file mode 100644
index 0000000..088ab98
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/LegacyNumericRangeQueryNode.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.nodes;
+
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.FieldType.LegacyNumericType;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+
+/**
+ * This query node represents a range query composed by {@link LegacyNumericQueryNode}
+ * bounds, which means the bound values are {@link Number}s.
+ * 
+ * @see LegacyNumericQueryNode
+ * @see AbstractRangeQueryNode
+ * @deprecated Index with Points instead and use {@link PointRangeQueryNode} instead.
+ */
+@Deprecated
+public class LegacyNumericRangeQueryNode extends
+    AbstractRangeQueryNode<LegacyNumericQueryNode> {
+  
+  public LegacyNumericConfig numericConfig; 
+  
+  /**
+   * Constructs a {@link LegacyNumericRangeQueryNode} object using the given
+   * {@link LegacyNumericQueryNode} as its bounds and {@link LegacyNumericConfig}.
+   * 
+   * @param lower the lower bound
+   * @param upper the upper bound
+   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
+   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
+   * @param numericConfig the {@link LegacyNumericConfig} that represents associated with the upper and lower bounds
+   * 
+   * @see #setBounds(LegacyNumericQueryNode, LegacyNumericQueryNode, boolean, boolean, LegacyNumericConfig)
+   */
+  public LegacyNumericRangeQueryNode(LegacyNumericQueryNode lower, LegacyNumericQueryNode upper,
+      boolean lowerInclusive, boolean upperInclusive, LegacyNumericConfig numericConfig) throws QueryNodeException {
+    setBounds(lower, upper, lowerInclusive, upperInclusive, numericConfig);
+  }
+  
+  private static LegacyNumericType getNumericDataType(Number number) throws QueryNodeException {
+    
+    if (number instanceof Long) {
+      return FieldType.LegacyNumericType.LONG;
+    } else if (number instanceof Integer) {
+      return FieldType.LegacyNumericType.INT;
+    } else if (number instanceof Double) {
+      return LegacyNumericType.DOUBLE;
+    } else if (number instanceof Float) {
+      return FieldType.LegacyNumericType.FLOAT;
+    } else {
+      throw new QueryNodeException(
+          new MessageImpl(
+              QueryParserMessages.NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY,
+              number.getClass()));
+    }
+    
+  }
+  
+  /**
+   * Sets the upper and lower bounds of this range query node and the
+   * {@link LegacyNumericConfig} associated with these bounds.
+   * 
+   * @param lower the lower bound
+   * @param upper the upper bound
+   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
+   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
+   * @param numericConfig the {@link LegacyNumericConfig} that represents associated with the upper and lower bounds
+   * 
+   */
+  public void setBounds(LegacyNumericQueryNode lower, LegacyNumericQueryNode upper,
+      boolean lowerInclusive, boolean upperInclusive, LegacyNumericConfig numericConfig) throws QueryNodeException {
+    
+    if (numericConfig == null) {
+      throw new IllegalArgumentException("numericConfig cannot be null!");
+    }
+    
+    LegacyNumericType lowerNumberType, upperNumberType;
+    
+    if (lower != null && lower.getValue() != null) {
+      lowerNumberType = getNumericDataType(lower.getValue());
+    } else {
+      lowerNumberType = null;
+    }
+    
+    if (upper != null && upper.getValue() != null) {
+      upperNumberType = getNumericDataType(upper.getValue());
+    } else {
+      upperNumberType = null;
+    }
+    
+    if (lowerNumberType != null
+        && !lowerNumberType.equals(numericConfig.getType())) {
+      throw new IllegalArgumentException(
+          "lower value's type should be the same as numericConfig type: "
+              + lowerNumberType + " != " + numericConfig.getType());
+    }
+    
+    if (upperNumberType != null
+        && !upperNumberType.equals(numericConfig.getType())) {
+      throw new IllegalArgumentException(
+          "upper value's type should be the same as numericConfig type: "
+              + upperNumberType + " != " + numericConfig.getType());
+    }
+    
+    super.setBounds(lower, upper, lowerInclusive, upperInclusive);
+    this.numericConfig = numericConfig;
+    
+  }
+  
+  /**
+   * Returns the {@link LegacyNumericConfig} associated with the lower and upper bounds.
+   * 
+   * @return the {@link LegacyNumericConfig} associated with the lower and upper bounds
+   */
+  public LegacyNumericConfig getNumericConfig() {
+    return this.numericConfig;
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("<numericRange lowerInclusive='");
+    
+    sb.append(isLowerInclusive()).append("' upperInclusive='").append(
+        isUpperInclusive()).append(
+        "' precisionStep='" + numericConfig.getPrecisionStep()).append(
+        "' type='" + numericConfig.getType()).append("'>\n");
+    
+    sb.append(getLowerBound()).append('\n');
+    sb.append(getUpperBound()).append('\n');
+    sb.append("</numericRange>");
+    
+    return sb.toString();
+    
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericQueryNode.java
deleted file mode 100644
index 7509a39..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericQueryNode.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.nodes;
-
-import java.text.NumberFormat;
-import java.util.Locale;
-
-import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
-import org.apache.lucene.queryparser.flexible.core.nodes.FieldValuePairQueryNode;
-import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
-import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
-import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax.Type;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-
-/**
- * This query node represents a field query that holds a numeric value. It is
- * similar to {@link FieldQueryNode}, however the {@link #getValue()} returns a
- * {@link Number}.
- * 
- * @see NumericConfig
- */
-public class NumericQueryNode extends QueryNodeImpl implements
-    FieldValuePairQueryNode<Number> {
-  
-  private NumberFormat numberFormat;
-  
-  private CharSequence field;
-  
-  private Number value;
-  
-  /**
-   * Creates a {@link NumericQueryNode} object using the given field,
-   * {@link Number} value and {@link NumberFormat} used to convert the value to
-   * {@link String}.
-   * 
-   * @param field the field associated with this query node
-   * @param value the value hold by this node
-   * @param numberFormat the {@link NumberFormat} used to convert the value to {@link String}
-   */
-  public NumericQueryNode(CharSequence field, Number value,
-      NumberFormat numberFormat) {
-    
-    super();
-    
-    setNumberFormat(numberFormat);
-    setField(field);
-    setValue(value);
-    
-  }
-  
-  /**
-   * Returns the field associated with this node.
-   * 
-   * @return the field associated with this node
-   */
-  @Override
-  public CharSequence getField() {
-    return this.field;
-  }
-  
-  /**
-   * Sets the field associated with this node.
-   * 
-   * @param fieldName the field associated with this node
-   */
-  @Override
-  public void setField(CharSequence fieldName) {
-    this.field = fieldName;
-  }
-  
-  /**
-   * This method is used to get the value converted to {@link String} and
-   * escaped using the given {@link EscapeQuerySyntax}.
-   * 
-   * @param escaper the {@link EscapeQuerySyntax} used to escape the value {@link String}
-   * 
-   * @return the value converte to {@link String} and escaped
-   */
-  protected CharSequence getTermEscaped(EscapeQuerySyntax escaper) {
-    return escaper.escape(numberFormat.format(this.value),
-        Locale.ROOT, Type.NORMAL);
-  }
-  
-  @Override
-  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
-    if (isDefaultField(this.field)) {
-      return getTermEscaped(escapeSyntaxParser);
-    } else {
-      return this.field + ":" + getTermEscaped(escapeSyntaxParser);
-    }
-  }
-  
-  /**
-   * Sets the {@link NumberFormat} used to convert the value to {@link String}.
-   * 
-   * @param format the {@link NumberFormat} used to convert the value to {@link String}
-   */
-  public void setNumberFormat(NumberFormat format) {
-    this.numberFormat = format;
-  }
-  
-  /**
-   * Returns the {@link NumberFormat} used to convert the value to {@link String}.
-   * 
-   * @return the {@link NumberFormat} used to convert the value to {@link String}
-   */
-  public NumberFormat getNumberFormat() {
-    return this.numberFormat;
-  }
-  
-  /**
-   * Returns the numeric value as {@link Number}.
-   * 
-   * @return the numeric value
-   */
-  @Override
-  public Number getValue() {
-    return value;
-  }
-  
-  /**
-   * Sets the numeric value.
-   * 
-   * @param value the numeric value
-   */
-  @Override
-  public void setValue(Number value) {
-    this.value = value;
-  }
-  
-  @Override
-  public String toString() {
-    return "<numeric field='" + this.field + "' number='"
-        + numberFormat.format(value) + "'/>";
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericRangeQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericRangeQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericRangeQueryNode.java
deleted file mode 100644
index c132aa1..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/NumericRangeQueryNode.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.nodes;
-
-import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
-import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
-import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-
-/**
- * This query node represents a range query composed by {@link NumericQueryNode}
- * bounds, which means the bound values are {@link Number}s.
- * 
- * @see NumericQueryNode
- * @see AbstractRangeQueryNode
- */
-public class NumericRangeQueryNode extends
-    AbstractRangeQueryNode<NumericQueryNode> {
-  
-  public NumericConfig numericConfig; 
-  
-  /**
-   * Constructs a {@link NumericRangeQueryNode} object using the given
-   * {@link NumericQueryNode} as its bounds and {@link NumericConfig}.
-   * 
-   * @param lower the lower bound
-   * @param upper the upper bound
-   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
-   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
-   * @param numericConfig the {@link NumericConfig} that represents associated with the upper and lower bounds
-   * 
-   * @see #setBounds(NumericQueryNode, NumericQueryNode, boolean, boolean, NumericConfig)
-   */
-  public NumericRangeQueryNode(NumericQueryNode lower, NumericQueryNode upper,
-      boolean lowerInclusive, boolean upperInclusive, NumericConfig numericConfig) throws QueryNodeException {
-    setBounds(lower, upper, lowerInclusive, upperInclusive, numericConfig);
-  }
-  
-  private static LegacyNumericType getNumericDataType(Number number) throws QueryNodeException {
-    
-    if (number instanceof Long) {
-      return FieldType.LegacyNumericType.LONG;
-    } else if (number instanceof Integer) {
-      return FieldType.LegacyNumericType.INT;
-    } else if (number instanceof Double) {
-      return LegacyNumericType.DOUBLE;
-    } else if (number instanceof Float) {
-      return FieldType.LegacyNumericType.FLOAT;
-    } else {
-      throw new QueryNodeException(
-          new MessageImpl(
-              QueryParserMessages.NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY,
-              number.getClass()));
-    }
-    
-  }
-  
-  /**
-   * Sets the upper and lower bounds of this range query node and the
-   * {@link NumericConfig} associated with these bounds.
-   * 
-   * @param lower the lower bound
-   * @param upper the upper bound
-   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
-   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
-   * @param numericConfig the {@link NumericConfig} that represents associated with the upper and lower bounds
-   * 
-   */
-  public void setBounds(NumericQueryNode lower, NumericQueryNode upper,
-      boolean lowerInclusive, boolean upperInclusive, NumericConfig numericConfig) throws QueryNodeException {
-    
-    if (numericConfig == null) {
-      throw new IllegalArgumentException("numericConfig cannot be null!");
-    }
-    
-    LegacyNumericType lowerNumberType, upperNumberType;
-    
-    if (lower != null && lower.getValue() != null) {
-      lowerNumberType = getNumericDataType(lower.getValue());
-    } else {
-      lowerNumberType = null;
-    }
-    
-    if (upper != null && upper.getValue() != null) {
-      upperNumberType = getNumericDataType(upper.getValue());
-    } else {
-      upperNumberType = null;
-    }
-    
-    if (lowerNumberType != null
-        && !lowerNumberType.equals(numericConfig.getType())) {
-      throw new IllegalArgumentException(
-          "lower value's type should be the same as numericConfig type: "
-              + lowerNumberType + " != " + numericConfig.getType());
-    }
-    
-    if (upperNumberType != null
-        && !upperNumberType.equals(numericConfig.getType())) {
-      throw new IllegalArgumentException(
-          "upper value's type should be the same as numericConfig type: "
-              + upperNumberType + " != " + numericConfig.getType());
-    }
-    
-    super.setBounds(lower, upper, lowerInclusive, upperInclusive);
-    this.numericConfig = numericConfig;
-    
-  }
-  
-  /**
-   * Returns the {@link NumericConfig} associated with the lower and upper bounds.
-   * 
-   * @return the {@link NumericConfig} associated with the lower and upper bounds
-   */
-  public NumericConfig getNumericConfig() {
-    return this.numericConfig;
-  }
-  
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("<numericRange lowerInclusive='");
-    
-    sb.append(isLowerInclusive()).append("' upperInclusive='").append(
-        isUpperInclusive()).append(
-        "' precisionStep='" + numericConfig.getPrecisionStep()).append(
-        "' type='" + numericConfig.getType()).append("'>\n");
-    
-    sb.append(getLowerBound()).append('\n');
-    sb.append(getUpperBound()).append('\n');
-    sb.append("</numericRange>");
-    
-    return sb.toString();
-    
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointQueryNode.java
new file mode 100644
index 0000000..6d4cba7
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointQueryNode.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.nodes;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldValuePairQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax.Type;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+
+/**
+ * This query node represents a field query that holds a point value. It is
+ * similar to {@link FieldQueryNode}, however the {@link #getValue()} returns a
+ * {@link Number}.
+ * 
+ * @see PointsConfig
+ */
+public class PointQueryNode extends QueryNodeImpl implements
+    FieldValuePairQueryNode<Number> {
+  
+  private NumberFormat numberFormat;
+  
+  private CharSequence field;
+  
+  private Number value;
+  
+  /**
+   * Creates a {@link PointQueryNode} object using the given field,
+   * {@link Number} value and {@link NumberFormat} used to convert the value to
+   * {@link String}.
+   * 
+   * @param field the field associated with this query node
+   * @param value the value hold by this node
+   * @param numberFormat the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public PointQueryNode(CharSequence field, Number value,
+      NumberFormat numberFormat) {
+    
+    super();
+    
+    setNumberFormat(numberFormat);
+    setField(field);
+    setValue(value);
+    
+  }
+  
+  /**
+   * Returns the field associated with this node.
+   * 
+   * @return the field associated with this node
+   */
+  @Override
+  public CharSequence getField() {
+    return this.field;
+  }
+  
+  /**
+   * Sets the field associated with this node.
+   * 
+   * @param fieldName the field associated with this node
+   */
+  @Override
+  public void setField(CharSequence fieldName) {
+    this.field = fieldName;
+  }
+  
+  /**
+   * This method is used to get the value converted to {@link String} and
+   * escaped using the given {@link EscapeQuerySyntax}.
+   * 
+   * @param escaper the {@link EscapeQuerySyntax} used to escape the value {@link String}
+   * 
+   * @return the value converte to {@link String} and escaped
+   */
+  protected CharSequence getTermEscaped(EscapeQuerySyntax escaper) {
+    return escaper.escape(numberFormat.format(this.value),
+        Locale.ROOT, Type.NORMAL);
+  }
+  
+  @Override
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (isDefaultField(this.field)) {
+      return getTermEscaped(escapeSyntaxParser);
+    } else {
+      return this.field + ":" + getTermEscaped(escapeSyntaxParser);
+    }
+  }
+  
+  /**
+   * Sets the {@link NumberFormat} used to convert the value to {@link String}.
+   * 
+   * @param format the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public void setNumberFormat(NumberFormat format) {
+    this.numberFormat = format;
+  }
+  
+  /**
+   * Returns the {@link NumberFormat} used to convert the value to {@link String}.
+   * 
+   * @return the {@link NumberFormat} used to convert the value to {@link String}
+   */
+  public NumberFormat getNumberFormat() {
+    return this.numberFormat;
+  }
+  
+  /**
+   * Returns the numeric value as {@link Number}.
+   * 
+   * @return the numeric value
+   */
+  @Override
+  public Number getValue() {
+    return value;
+  }
+  
+  /**
+   * Sets the numeric value.
+   * 
+   * @param value the numeric value
+   */
+  @Override
+  public void setValue(Number value) {
+    this.value = value;
+  }
+  
+  @Override
+  public String toString() {
+    return "<numeric field='" + this.field + "' number='"
+        + numberFormat.format(value) + "'/>";
+  }
+  
+}


[2/3] lucene-solr git commit: LUCENE-7089, LUCENE-7075: add points to flexible queryparser to replace legacy numerics support

Posted by rm...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointRangeQueryNode.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointRangeQueryNode.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointRangeQueryNode.java
new file mode 100644
index 0000000..cb838fc
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/PointRangeQueryNode.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.nodes;
+
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+
+/**
+ * This query node represents a range query composed by {@link PointQueryNode}
+ * bounds, which means the bound values are {@link Number}s.
+ * 
+ * @see PointQueryNode
+ * @see AbstractRangeQueryNode
+ */
+public class PointRangeQueryNode extends AbstractRangeQueryNode<PointQueryNode> {
+  
+  public PointsConfig numericConfig; 
+  
+  /**
+   * Constructs a {@link PointRangeQueryNode} object using the given
+   * {@link PointQueryNode} as its bounds and {@link PointsConfig}.
+   * 
+   * @param lower the lower bound
+   * @param upper the upper bound
+   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
+   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
+   * @param numericConfig the {@link PointsConfig} that represents associated with the upper and lower bounds
+   * 
+   * @see #setBounds(PointQueryNode, PointQueryNode, boolean, boolean, PointsConfig)
+   */
+  public PointRangeQueryNode(PointQueryNode lower, PointQueryNode upper,
+      boolean lowerInclusive, boolean upperInclusive, PointsConfig numericConfig) throws QueryNodeException {
+    setBounds(lower, upper, lowerInclusive, upperInclusive, numericConfig);
+  }
+  
+  /**
+   * Sets the upper and lower bounds of this range query node and the
+   * {@link PointsConfig} associated with these bounds.
+   * 
+   * @param lower the lower bound
+   * @param upper the upper bound
+   * @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
+   * @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
+   * @param pointsConfig the {@link PointsConfig} that represents associated with the upper and lower bounds
+   * 
+   */
+  public void setBounds(PointQueryNode lower, PointQueryNode upper,
+      boolean lowerInclusive, boolean upperInclusive, PointsConfig pointsConfig) throws QueryNodeException {
+    
+    if (pointsConfig == null) {
+      throw new IllegalArgumentException("pointsConfig cannot be null!");
+    }
+    
+    Class<? extends Number> lowerNumberType, upperNumberType;
+    
+    if (lower != null && lower.getValue() != null) {
+      lowerNumberType = lower.getValue().getClass();
+    } else {
+      lowerNumberType = null;
+    }
+    
+    if (upper != null && upper.getValue() != null) {
+      upperNumberType = upper.getValue().getClass();
+    } else {
+      upperNumberType = null;
+    }
+    
+    if (lowerNumberType != null
+        && !lowerNumberType.equals(pointsConfig.getType())) {
+      throw new IllegalArgumentException(
+          "lower value's type should be the same as numericConfig type: "
+              + lowerNumberType + " != " + pointsConfig.getType());
+    }
+    
+    if (upperNumberType != null
+        && !upperNumberType.equals(pointsConfig.getType())) {
+      throw new IllegalArgumentException(
+          "upper value's type should be the same as numericConfig type: "
+              + upperNumberType + " != " + pointsConfig.getType());
+    }
+    
+    super.setBounds(lower, upper, lowerInclusive, upperInclusive);
+    this.numericConfig = pointsConfig;
+  }
+  
+  /**
+   * Returns the {@link PointsConfig} associated with the lower and upper bounds.
+   * 
+   * @return the {@link PointsConfig} associated with the lower and upper bounds
+   */
+  public PointsConfig getPointsConfig() {
+    return this.numericConfig;
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("<pointRange lowerInclusive='");
+    sb.append(isLowerInclusive());
+    sb.append("' upperInclusive='");
+    sb.append(isUpperInclusive());
+    sb.append("' type='");
+    sb.append(numericConfig.getType().getSimpleName());
+    sb.append("'>\n");
+    sb.append(getLowerBound()).append('\n');
+    sb.append(getUpperBound()).append('\n');
+    sb.append("</pointRange>");
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericQueryNodeProcessor.java
new file mode 100644
index 0000000..8b71824
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericQueryNodeProcessor.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.processors;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.RangeQueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
+
+/**
+ * This processor is used to convert {@link FieldQueryNode}s to
+ * {@link LegacyNumericRangeQueryNode}s. It looks for
+ * {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} set in the {@link FieldConfig} of
+ * every {@link FieldQueryNode} found. If
+ * {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} is found, it considers that
+ * {@link FieldQueryNode} to be a numeric query and convert it to
+ * {@link LegacyNumericRangeQueryNode} with upper and lower inclusive and lower and
+ * upper equals to the value represented by the {@link FieldQueryNode} converted
+ * to {@link Number}. It means that <b>field:1</b> is converted to <b>field:[1
+ * TO 1]</b>. <br>
+ * <br>
+ * Note that {@link FieldQueryNode}s children of a
+ * {@link RangeQueryNode} are ignored.
+ * 
+ * @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
+ * @see FieldQueryNode
+ * @see LegacyNumericConfig
+ * @see LegacyNumericQueryNode
+ * @deprecated Index with points and use {@link PointQueryNodeProcessor} instead.
+ */
+@Deprecated
+public class LegacyNumericQueryNodeProcessor extends QueryNodeProcessorImpl {
+  
+  /**
+   * Constructs a {@link LegacyNumericQueryNodeProcessor} object.
+   */
+  public LegacyNumericQueryNodeProcessor() {
+  // empty constructor
+  }
+  
+  @Override
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+    
+    if (node instanceof FieldQueryNode
+        && !(node.getParent() instanceof RangeQueryNode)) {
+      
+      QueryConfigHandler config = getQueryConfigHandler();
+      
+      if (config != null) {
+        FieldQueryNode fieldNode = (FieldQueryNode) node;
+        FieldConfig fieldConfig = config.getFieldConfig(fieldNode
+            .getFieldAsString());
+        
+        if (fieldConfig != null) {
+          LegacyNumericConfig numericConfig = fieldConfig
+              .get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG);
+          
+          if (numericConfig != null) {
+            
+            NumberFormat numberFormat = numericConfig.getNumberFormat();
+            String text = fieldNode.getTextAsString();
+            Number number = null;
+            
+            if (text.length() > 0) {
+              
+              try {
+                number = numberFormat.parse(text);
+                
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
+                        .getTextAsString(), numberFormat.getClass()
+                        .getCanonicalName()), e);
+              }
+              
+              switch (numericConfig.getType()) {
+                case LONG:
+                  number = number.longValue();
+                  break;
+                case INT:
+                  number = number.intValue();
+                  break;
+                case DOUBLE:
+                  number = number.doubleValue();
+                  break;
+                case FLOAT:
+                  number = number.floatValue();
+              }
+              
+            } else {
+              throw new QueryNodeParseException(new MessageImpl(
+                  QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.getFieldAsString()));
+            }
+            
+            LegacyNumericQueryNode lowerNode = new LegacyNumericQueryNode(fieldNode
+                .getField(), number, numberFormat);
+            LegacyNumericQueryNode upperNode = new LegacyNumericQueryNode(fieldNode
+                .getField(), number, numberFormat);
+            
+            return new LegacyNumericRangeQueryNode(lowerNode, upperNode, true, true,
+                numericConfig);
+            
+          }
+          
+        }
+        
+      }
+      
+    }
+    
+    return node;
+    
+  }
+  
+  @Override
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+    return node;
+  }
+  
+  @Override
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+    return children;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericRangeQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericRangeQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericRangeQueryNodeProcessor.java
new file mode 100644
index 0000000..5a54b7b
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/LegacyNumericRangeQueryNodeProcessor.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.processors;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
+
+/**
+ * This processor is used to convert {@link TermRangeQueryNode}s to
+ * {@link LegacyNumericRangeQueryNode}s. It looks for
+ * {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} set in the {@link FieldConfig} of
+ * every {@link TermRangeQueryNode} found. If
+ * {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} is found, it considers that
+ * {@link TermRangeQueryNode} to be a numeric range query and convert it to
+ * {@link LegacyNumericRangeQueryNode}.
+ * 
+ * @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
+ * @see TermRangeQueryNode
+ * @see LegacyNumericConfig
+ * @see LegacyNumericRangeQueryNode
+ * @deprecated Index with points and use {@link PointRangeQueryNodeProcessor} instead.
+ */
+@Deprecated
+public class LegacyNumericRangeQueryNodeProcessor extends QueryNodeProcessorImpl {
+  
+  /**
+   * Constructs an empty {@link LegacyNumericRangeQueryNode} object.
+   */
+  public LegacyNumericRangeQueryNodeProcessor() {
+  // empty constructor
+  }
+  
+  @Override
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+    
+    if (node instanceof TermRangeQueryNode) {
+      QueryConfigHandler config = getQueryConfigHandler();
+      
+      if (config != null) {
+        TermRangeQueryNode termRangeNode = (TermRangeQueryNode) node;
+        FieldConfig fieldConfig = config.getFieldConfig(StringUtils
+            .toString(termRangeNode.getField()));
+        
+        if (fieldConfig != null) {
+          
+          LegacyNumericConfig numericConfig = fieldConfig
+              .get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG);
+          
+          if (numericConfig != null) {
+            
+            FieldQueryNode lower = termRangeNode.getLowerBound();
+            FieldQueryNode upper = termRangeNode.getUpperBound();
+            
+            String lowerText = lower.getTextAsString();
+            String upperText = upper.getTextAsString();
+            NumberFormat numberFormat = numericConfig.getNumberFormat();
+            Number lowerNumber = null, upperNumber = null;
+            
+             if (lowerText.length() > 0) {
+              
+              try {
+                lowerNumber = numberFormat.parse(lowerText);
+                
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
+                        .getTextAsString(), numberFormat.getClass()
+                        .getCanonicalName()), e);
+              }
+              
+            }
+            
+             if (upperText.length() > 0) {
+            
+              try {
+                upperNumber = numberFormat.parse(upperText);
+                
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
+                        .getTextAsString(), numberFormat.getClass()
+                        .getCanonicalName()), e);
+              }
+            
+            }
+            
+            switch (numericConfig.getType()) {
+              case LONG:
+                if (upperNumber != null) upperNumber = upperNumber.longValue();
+                if (lowerNumber != null) lowerNumber = lowerNumber.longValue();
+                break;
+              case INT:
+                if (upperNumber != null) upperNumber = upperNumber.intValue();
+                if (lowerNumber != null) lowerNumber = lowerNumber.intValue();
+                break;
+              case DOUBLE:
+                if (upperNumber != null) upperNumber = upperNumber.doubleValue();
+                if (lowerNumber != null) lowerNumber = lowerNumber.doubleValue();
+                break;
+              case FLOAT:
+                if (upperNumber != null) upperNumber = upperNumber.floatValue();
+                if (lowerNumber != null) lowerNumber = lowerNumber.floatValue();
+            }
+            
+            LegacyNumericQueryNode lowerNode = new LegacyNumericQueryNode(
+                termRangeNode.getField(), lowerNumber, numberFormat);
+            LegacyNumericQueryNode upperNode = new LegacyNumericQueryNode(
+                termRangeNode.getField(), upperNumber, numberFormat);
+            
+            boolean lowerInclusive = termRangeNode.isLowerInclusive();
+            boolean upperInclusive = termRangeNode.isUpperInclusive();
+            
+            return new LegacyNumericRangeQueryNode(lowerNode, upperNode,
+                lowerInclusive, upperInclusive, numericConfig);
+            
+          }
+          
+        }
+        
+      }
+      
+    }
+    
+    return node;
+    
+  }
+  
+  @Override
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+    return node;
+  }
+  
+  @Override
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+    return children;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericQueryNodeProcessor.java
deleted file mode 100644
index 10bd6ba..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericQueryNodeProcessor.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.processors;
-
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.List;
-
-import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
-import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
-import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
-import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
-import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
-import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
-import org.apache.lucene.queryparser.flexible.core.nodes.RangeQueryNode;
-import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericRangeQueryNode;
-
-/**
- * This processor is used to convert {@link FieldQueryNode}s to
- * {@link NumericRangeQueryNode}s. It looks for
- * {@link ConfigurationKeys#NUMERIC_CONFIG} set in the {@link FieldConfig} of
- * every {@link FieldQueryNode} found. If
- * {@link ConfigurationKeys#NUMERIC_CONFIG} is found, it considers that
- * {@link FieldQueryNode} to be a numeric query and convert it to
- * {@link NumericRangeQueryNode} with upper and lower inclusive and lower and
- * upper equals to the value represented by the {@link FieldQueryNode} converted
- * to {@link Number}. It means that <b>field:1</b> is converted to <b>field:[1
- * TO 1]</b>. <br>
- * <br>
- * Note that {@link FieldQueryNode}s children of a
- * {@link RangeQueryNode} are ignored.
- * 
- * @see ConfigurationKeys#NUMERIC_CONFIG
- * @see FieldQueryNode
- * @see NumericConfig
- * @see NumericQueryNode
- */
-public class NumericQueryNodeProcessor extends QueryNodeProcessorImpl {
-  
-  /**
-   * Constructs a {@link NumericQueryNodeProcessor} object.
-   */
-  public NumericQueryNodeProcessor() {
-  // empty constructor
-  }
-  
-  @Override
-  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
-    
-    if (node instanceof FieldQueryNode
-        && !(node.getParent() instanceof RangeQueryNode)) {
-      
-      QueryConfigHandler config = getQueryConfigHandler();
-      
-      if (config != null) {
-        FieldQueryNode fieldNode = (FieldQueryNode) node;
-        FieldConfig fieldConfig = config.getFieldConfig(fieldNode
-            .getFieldAsString());
-        
-        if (fieldConfig != null) {
-          NumericConfig numericConfig = fieldConfig
-              .get(ConfigurationKeys.NUMERIC_CONFIG);
-          
-          if (numericConfig != null) {
-            
-            NumberFormat numberFormat = numericConfig.getNumberFormat();
-            String text = fieldNode.getTextAsString();
-            Number number = null;
-            
-            if (text.length() > 0) {
-              
-              try {
-                number = numberFormat.parse(text);
-                
-              } catch (ParseException e) {
-                throw new QueryNodeParseException(new MessageImpl(
-                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
-                        .getTextAsString(), numberFormat.getClass()
-                        .getCanonicalName()), e);
-              }
-              
-              switch (numericConfig.getType()) {
-                case LONG:
-                  number = number.longValue();
-                  break;
-                case INT:
-                  number = number.intValue();
-                  break;
-                case DOUBLE:
-                  number = number.doubleValue();
-                  break;
-                case FLOAT:
-                  number = number.floatValue();
-              }
-              
-            } else {
-              throw new QueryNodeParseException(new MessageImpl(
-                  QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.getFieldAsString()));
-            }
-            
-            NumericQueryNode lowerNode = new NumericQueryNode(fieldNode
-                .getField(), number, numberFormat);
-            NumericQueryNode upperNode = new NumericQueryNode(fieldNode
-                .getField(), number, numberFormat);
-            
-            return new NumericRangeQueryNode(lowerNode, upperNode, true, true,
-                numericConfig);
-            
-          }
-          
-        }
-        
-      }
-      
-    }
-    
-    return node;
-    
-  }
-  
-  @Override
-  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
-    return node;
-  }
-  
-  @Override
-  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
-      throws QueryNodeException {
-    return children;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericRangeQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericRangeQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericRangeQueryNodeProcessor.java
deleted file mode 100644
index bbe5284..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/NumericRangeQueryNodeProcessor.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.flexible.standard.processors;
-
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.List;
-
-import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
-import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
-import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
-import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
-import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
-import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
-import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
-import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
-import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
-import org.apache.lucene.queryparser.flexible.standard.config.NumericConfig;
-import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.NumericRangeQueryNode;
-import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
-
-/**
- * This processor is used to convert {@link TermRangeQueryNode}s to
- * {@link NumericRangeQueryNode}s. It looks for
- * {@link ConfigurationKeys#NUMERIC_CONFIG} set in the {@link FieldConfig} of
- * every {@link TermRangeQueryNode} found. If
- * {@link ConfigurationKeys#NUMERIC_CONFIG} is found, it considers that
- * {@link TermRangeQueryNode} to be a numeric range query and convert it to
- * {@link NumericRangeQueryNode}.
- * 
- * @see ConfigurationKeys#NUMERIC_CONFIG
- * @see TermRangeQueryNode
- * @see NumericConfig
- * @see NumericRangeQueryNode
- */
-public class NumericRangeQueryNodeProcessor extends QueryNodeProcessorImpl {
-  
-  /**
-   * Constructs an empty {@link NumericRangeQueryNode} object.
-   */
-  public NumericRangeQueryNodeProcessor() {
-  // empty constructor
-  }
-  
-  @Override
-  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
-    
-    if (node instanceof TermRangeQueryNode) {
-      QueryConfigHandler config = getQueryConfigHandler();
-      
-      if (config != null) {
-        TermRangeQueryNode termRangeNode = (TermRangeQueryNode) node;
-        FieldConfig fieldConfig = config.getFieldConfig(StringUtils
-            .toString(termRangeNode.getField()));
-        
-        if (fieldConfig != null) {
-          
-          NumericConfig numericConfig = fieldConfig
-              .get(ConfigurationKeys.NUMERIC_CONFIG);
-          
-          if (numericConfig != null) {
-            
-            FieldQueryNode lower = termRangeNode.getLowerBound();
-            FieldQueryNode upper = termRangeNode.getUpperBound();
-            
-            String lowerText = lower.getTextAsString();
-            String upperText = upper.getTextAsString();
-            NumberFormat numberFormat = numericConfig.getNumberFormat();
-            Number lowerNumber = null, upperNumber = null;
-            
-             if (lowerText.length() > 0) {
-              
-              try {
-                lowerNumber = numberFormat.parse(lowerText);
-                
-              } catch (ParseException e) {
-                throw new QueryNodeParseException(new MessageImpl(
-                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
-                        .getTextAsString(), numberFormat.getClass()
-                        .getCanonicalName()), e);
-              }
-              
-            }
-            
-             if (upperText.length() > 0) {
-            
-              try {
-                upperNumber = numberFormat.parse(upperText);
-                
-              } catch (ParseException e) {
-                throw new QueryNodeParseException(new MessageImpl(
-                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
-                        .getTextAsString(), numberFormat.getClass()
-                        .getCanonicalName()), e);
-              }
-            
-            }
-            
-            switch (numericConfig.getType()) {
-              case LONG:
-                if (upperNumber != null) upperNumber = upperNumber.longValue();
-                if (lowerNumber != null) lowerNumber = lowerNumber.longValue();
-                break;
-              case INT:
-                if (upperNumber != null) upperNumber = upperNumber.intValue();
-                if (lowerNumber != null) lowerNumber = lowerNumber.intValue();
-                break;
-              case DOUBLE:
-                if (upperNumber != null) upperNumber = upperNumber.doubleValue();
-                if (lowerNumber != null) lowerNumber = lowerNumber.doubleValue();
-                break;
-              case FLOAT:
-                if (upperNumber != null) upperNumber = upperNumber.floatValue();
-                if (lowerNumber != null) lowerNumber = lowerNumber.floatValue();
-            }
-            
-            NumericQueryNode lowerNode = new NumericQueryNode(
-                termRangeNode.getField(), lowerNumber, numberFormat);
-            NumericQueryNode upperNode = new NumericQueryNode(
-                termRangeNode.getField(), upperNumber, numberFormat);
-            
-            boolean lowerInclusive = termRangeNode.isLowerInclusive();
-            boolean upperInclusive = termRangeNode.isUpperInclusive();
-            
-            return new NumericRangeQueryNode(lowerNode, upperNode,
-                lowerInclusive, upperInclusive, numericConfig);
-            
-          }
-          
-        }
-        
-      }
-      
-    }
-    
-    return node;
-    
-  }
-  
-  @Override
-  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
-    return node;
-  }
-  
-  @Override
-  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
-      throws QueryNodeException {
-    return children;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointQueryNodeProcessor.java
new file mode 100644
index 0000000..81a8449
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointQueryNodeProcessor.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.processors;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.RangeQueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointRangeQueryNode;
+
+/**
+ * This processor is used to convert {@link FieldQueryNode}s to
+ * {@link PointRangeQueryNode}s. It looks for
+ * {@link ConfigurationKeys#POINTS_CONFIG} set in the {@link FieldConfig} of
+ * every {@link FieldQueryNode} found. If
+ * {@link ConfigurationKeys#POINTS_CONFIG} is found, it considers that
+ * {@link FieldQueryNode} to be a numeric query and convert it to
+ * {@link PointRangeQueryNode} with upper and lower inclusive and lower and
+ * upper equals to the value represented by the {@link FieldQueryNode} converted
+ * to {@link Number}. It means that <b>field:1</b> is converted to <b>field:[1
+ * TO 1]</b>. <br>
+ * <br>
+ * Note that {@link FieldQueryNode}s children of a
+ * {@link RangeQueryNode} are ignored.
+ * 
+ * @see ConfigurationKeys#POINTS_CONFIG
+ * @see FieldQueryNode
+ * @see PointsConfig
+ * @see PointQueryNode
+ */
+public class PointQueryNodeProcessor extends QueryNodeProcessorImpl {
+  
+  /**
+   * Constructs a {@link PointQueryNodeProcessor} object.
+   */
+  public PointQueryNodeProcessor() {
+  // empty constructor
+  }
+  
+  @Override
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+    
+    if (node instanceof FieldQueryNode
+        && !(node.getParent() instanceof RangeQueryNode)) {
+      
+      QueryConfigHandler config = getQueryConfigHandler();
+      
+      if (config != null) {
+        FieldQueryNode fieldNode = (FieldQueryNode) node;
+        FieldConfig fieldConfig = config.getFieldConfig(fieldNode
+            .getFieldAsString());
+        
+        if (fieldConfig != null) {
+          PointsConfig numericConfig = fieldConfig.get(ConfigurationKeys.POINTS_CONFIG);
+          
+          if (numericConfig != null) {
+            
+            NumberFormat numberFormat = numericConfig.getNumberFormat();
+            String text = fieldNode.getTextAsString();
+            Number number = null;
+            
+            if (text.length() > 0) {
+              
+              try {
+                number = numberFormat.parse(text);
+                
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
+                        .getTextAsString(), numberFormat.getClass()
+                        .getCanonicalName()), e);
+              }
+              
+              if (Integer.class.equals(numericConfig.getType())) {
+                number = number.intValue();
+              } else if (Long.class.equals(numericConfig.getType())) {
+                number = number.longValue();
+              } else if (Double.class.equals(numericConfig.getType())) {
+                number = number.doubleValue();
+              } else if (Float.class.equals(numericConfig.getType())) {
+                number = number.floatValue();
+              }
+              
+            } else {
+              throw new QueryNodeParseException(new MessageImpl(
+                  QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.getFieldAsString()));
+            }
+            
+            PointQueryNode lowerNode = new PointQueryNode(fieldNode.getField(), number, numberFormat);
+            PointQueryNode upperNode = new PointQueryNode(fieldNode.getField(), number, numberFormat);
+            
+            return new PointRangeQueryNode(lowerNode, upperNode, true, true, numericConfig);
+          }
+        }
+      }
+    }
+    return node;
+  }
+  
+  @Override
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+    return node;
+  }
+  
+  @Override
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children) throws QueryNodeException {
+    return children;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointRangeQueryNodeProcessor.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointRangeQueryNodeProcessor.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointRangeQueryNodeProcessor.java
new file mode 100644
index 0000000..2ffc437
--- /dev/null
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/PointRangeQueryNodeProcessor.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard.processors;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
+import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.PointRangeQueryNode;
+import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
+
+/**
+ * This processor is used to convert {@link TermRangeQueryNode}s to
+ * {@link PointRangeQueryNode}s. It looks for
+ * {@link ConfigurationKeys#POINTS_CONFIG} set in the {@link FieldConfig} of
+ * every {@link TermRangeQueryNode} found. If
+ * {@link ConfigurationKeys#POINTS_CONFIG} is found, it considers that
+ * {@link TermRangeQueryNode} to be a numeric range query and convert it to
+ * {@link PointRangeQueryNode}.
+ * 
+ * @see ConfigurationKeys#POINTS_CONFIG
+ * @see TermRangeQueryNode
+ * @see PointsConfig
+ * @see PointRangeQueryNode
+ */
+public class PointRangeQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+  /**
+   * Constructs an empty {@link PointRangeQueryNodeProcessor} object.
+   */
+  public PointRangeQueryNodeProcessor() {
+    // empty constructor
+  }
+
+  @Override
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+    if (node instanceof TermRangeQueryNode) {
+      QueryConfigHandler config = getQueryConfigHandler();
+
+      if (config != null) {
+        TermRangeQueryNode termRangeNode = (TermRangeQueryNode) node;
+        FieldConfig fieldConfig = config.getFieldConfig(StringUtils.toString(termRangeNode.getField()));
+
+        if (fieldConfig != null) {
+          PointsConfig numericConfig = fieldConfig.get(ConfigurationKeys.POINTS_CONFIG);
+
+          if (numericConfig != null) {
+            FieldQueryNode lower = termRangeNode.getLowerBound();
+            FieldQueryNode upper = termRangeNode.getUpperBound();
+
+            String lowerText = lower.getTextAsString();
+            String upperText = upper.getTextAsString();
+            NumberFormat numberFormat = numericConfig.getNumberFormat();
+            Number lowerNumber = null, upperNumber = null;
+
+            if (lowerText.length() > 0) {
+
+              try {
+                lowerNumber = numberFormat.parse(lowerText);
+
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
+                    .getTextAsString(), numberFormat.getClass()
+                    .getCanonicalName()), e);
+              }
+
+            }
+
+            if (upperText.length() > 0) {
+
+              try {
+                upperNumber = numberFormat.parse(upperText);
+
+              } catch (ParseException e) {
+                throw new QueryNodeParseException(new MessageImpl(
+                    QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
+                    .getTextAsString(), numberFormat.getClass()
+                    .getCanonicalName()), e);
+              }
+            }
+
+            if (Integer.class.equals(numericConfig.getType())) {
+              if (upperNumber != null) upperNumber = upperNumber.intValue();
+              if (lowerNumber != null) lowerNumber = lowerNumber.intValue();
+            } else if (Long.class.equals(numericConfig.getType())) {
+              if (upperNumber != null) upperNumber = upperNumber.longValue();
+              if (lowerNumber != null) lowerNumber = lowerNumber.longValue();
+            } else if (Double.class.equals(numericConfig.getType())) {
+              if (upperNumber != null) upperNumber = upperNumber.doubleValue();
+              if (lowerNumber != null) lowerNumber = lowerNumber.doubleValue();
+            } else if (Float.class.equals(numericConfig.getType())) {
+              if (upperNumber != null) upperNumber = upperNumber.floatValue();
+              if (lowerNumber != null) lowerNumber = lowerNumber.floatValue();
+            }
+
+            PointQueryNode lowerNode = new PointQueryNode(termRangeNode.getField(), lowerNumber, numberFormat);
+            PointQueryNode upperNode = new PointQueryNode(termRangeNode.getField(), upperNumber, numberFormat);
+
+            boolean lowerInclusive = termRangeNode.isLowerInclusive();
+            boolean upperInclusive = termRangeNode.isUpperInclusive();
+
+            return new PointRangeQueryNode(lowerNode, upperNode, lowerInclusive, upperInclusive, numericConfig);
+          }
+        }  
+      }
+    }
+    return node;
+  }
+
+  @Override
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+    return node;
+  }
+
+  @Override
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children) throws QueryNodeException {
+    return children;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/StandardQueryNodeProcessorPipeline.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/StandardQueryNodeProcessorPipeline.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/StandardQueryNodeProcessorPipeline.java
index 06f38c2..6e4a394 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/StandardQueryNodeProcessorPipeline.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/processors/StandardQueryNodeProcessorPipeline.java
@@ -55,8 +55,10 @@ public class StandardQueryNodeProcessorPipeline extends
     add(new FuzzyQueryNodeProcessor());
     add(new MatchAllDocsQueryNodeProcessor());
     add(new OpenRangeQueryNodeProcessor());
-    add(new NumericQueryNodeProcessor());
-    add(new NumericRangeQueryNodeProcessor());
+    add(new LegacyNumericQueryNodeProcessor());
+    add(new LegacyNumericRangeQueryNodeProcessor());
+    add(new PointQueryNodeProcessor());
+    add(new PointRangeQueryNodeProcessor());
     add(new LowercaseExpandedTermsQueryNodeProcessor());
     add(new TermRangeQueryNodeProcessor());
     add(new AllowLeadingWildcardProcessor());    

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89cc676f/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestLegacyNumericQueryParser.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestLegacyNumericQueryParser.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestLegacyNumericQueryParser.java
new file mode 100644
index 0000000..c6ab7f5
--- /dev/null
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestLegacyNumericQueryParser.java
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.queryparser.flexible.standard;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+import java.util.TimeZone;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.LegacyDoubleField;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType.LegacyNumericType;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.LegacyFloatField;
+import org.apache.lucene.document.LegacyIntField;
+import org.apache.lucene.document.LegacyLongField;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryparser.flexible.standard.config.NumberDateFormat;
+import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
+import org.apache.lucene.queryparser.flexible.standard.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestLegacyNumericQueryParser extends LuceneTestCase {
+  
+  private static enum NumberType {
+    NEGATIVE, ZERO, POSITIVE;
+  }
+  
+  final private static int[] DATE_STYLES = {DateFormat.FULL, DateFormat.LONG,
+      DateFormat.MEDIUM, DateFormat.SHORT};
+  
+  final private static int PRECISION_STEP = 8;
+  final private static String FIELD_NAME = "field";
+  private static Locale LOCALE;
+  private static TimeZone TIMEZONE;
+  private static Map<String,Number> RANDOM_NUMBER_MAP;
+  private static EscapeQuerySyntax ESCAPER = new EscapeQuerySyntaxImpl();
+  final private static String DATE_FIELD_NAME = "date";
+  private static int DATE_STYLE;
+  private static int TIME_STYLE;
+  
+  private static Analyzer ANALYZER;
+  
+  private static NumberFormat NUMBER_FORMAT;
+  
+  private static StandardQueryParser qp;
+  
+  private static NumberDateFormat DATE_FORMAT;
+  
+  private static Directory directory = null;
+  private static IndexReader reader = null;
+  private static IndexSearcher searcher = null;
+  
+  private static boolean checkDateFormatSanity(DateFormat dateFormat, long date) {
+    try {
+      return date == dateFormat.parse(dateFormat.format(new Date(date)))
+        .getTime();
+    } catch (ParseException e) {
+      return false;
+    }
+  }
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    ANALYZER = new MockAnalyzer(random());
+    
+    qp = new StandardQueryParser(ANALYZER);
+    
+    final HashMap<String,Number> randomNumberMap = new HashMap<>();
+    
+    SimpleDateFormat dateFormat;
+    long randomDate;
+    boolean dateFormatSanityCheckPass;
+    int count = 0;
+    do {
+      if (count > 100) {
+        fail("This test has problems to find a sane random DateFormat/NumberFormat. Stopped trying after 100 iterations.");
+      }
+      
+      dateFormatSanityCheckPass = true;
+      LOCALE = randomLocale(random());
+      TIMEZONE = randomTimeZone(random());
+      DATE_STYLE = randomDateStyle(random());
+      TIME_STYLE = randomDateStyle(random());
+      
+      // assumes localized date pattern will have at least year, month, day,
+      // hour, minute
+      dateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance(
+          DATE_STYLE, TIME_STYLE, LOCALE);
+      
+      // not all date patterns includes era, full year, timezone and second,
+      // so we add them here
+      dateFormat.applyPattern(dateFormat.toPattern() + " G s Z yyyy");
+      dateFormat.setTimeZone(TIMEZONE);
+      
+      DATE_FORMAT = new NumberDateFormat(dateFormat);
+      
+      do {
+        randomDate = random().nextLong();
+        
+        // prune date value so it doesn't pass in insane values to some
+        // calendars.
+        randomDate = randomDate % 3400000000000l;
+        
+        // truncate to second
+        randomDate = (randomDate / 1000L) * 1000L;
+        
+        // only positive values
+        randomDate = Math.abs(randomDate);
+      } while (randomDate == 0L);
+      
+      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, randomDate);
+      
+      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, 0);
+      
+      dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat,
+          -randomDate);
+      
+      count++;
+    } while (!dateFormatSanityCheckPass);
+    
+    NUMBER_FORMAT = NumberFormat.getNumberInstance(LOCALE);
+    NUMBER_FORMAT.setMaximumFractionDigits((random().nextInt() & 20) + 1);
+    NUMBER_FORMAT.setMinimumFractionDigits((random().nextInt() & 20) + 1);
+    NUMBER_FORMAT.setMaximumIntegerDigits((random().nextInt() & 20) + 1);
+    NUMBER_FORMAT.setMinimumIntegerDigits((random().nextInt() & 20) + 1);
+    
+    double randomDouble;
+    long randomLong;
+    int randomInt;
+    float randomFloat;
+    
+    while ((randomLong = normalizeNumber(Math.abs(random().nextLong()))
+        .longValue()) == 0L)
+      ;
+    while ((randomDouble = normalizeNumber(Math.abs(random().nextDouble()))
+        .doubleValue()) == 0.0)
+      ;
+    while ((randomFloat = normalizeNumber(Math.abs(random().nextFloat()))
+        .floatValue()) == 0.0f)
+      ;
+    while ((randomInt = normalizeNumber(Math.abs(random().nextInt())).intValue()) == 0)
+      ;
+    
+    randomNumberMap.put(LegacyNumericType.LONG.name(), randomLong);
+    randomNumberMap.put(FieldType.LegacyNumericType.INT.name(), randomInt);
+    randomNumberMap.put(LegacyNumericType.FLOAT.name(), randomFloat);
+    randomNumberMap.put(LegacyNumericType.DOUBLE.name(), randomDouble);
+    randomNumberMap.put(DATE_FIELD_NAME, randomDate);
+    
+    RANDOM_NUMBER_MAP = Collections.unmodifiableMap(randomNumberMap);
+    
+    directory = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
+        newIndexWriterConfig(new MockAnalyzer(random()))
+            .setMaxBufferedDocs(TestUtil.nextInt(random(), 50, 1000))
+            .setMergePolicy(newLogMergePolicy()));
+    
+    Document doc = new Document();
+    HashMap<String,LegacyNumericConfig> numericConfigMap = new HashMap<>();
+    HashMap<String,Field> numericFieldMap = new HashMap<>();
+    qp.setLegacyNumericConfigMap(numericConfigMap);
+    
+    for (LegacyNumericType type : LegacyNumericType.values()) {
+      numericConfigMap.put(type.name(), new LegacyNumericConfig(PRECISION_STEP,
+          NUMBER_FORMAT, type));
+
+      FieldType ft = new FieldType(LegacyIntField.TYPE_NOT_STORED);
+      ft.setNumericType(type);
+      ft.setStored(true);
+      ft.setNumericPrecisionStep(PRECISION_STEP);
+      ft.freeze();
+      final Field field;
+
+      switch(type) {
+      case INT:
+        field = new LegacyIntField(type.name(), 0, ft);
+        break;
+      case FLOAT:
+        field = new LegacyFloatField(type.name(), 0.0f, ft);
+        break;
+      case LONG:
+        field = new LegacyLongField(type.name(), 0l, ft);
+        break;
+      case DOUBLE:
+        field = new LegacyDoubleField(type.name(), 0.0, ft);
+        break;
+      default:
+        fail();
+        field = null;
+      }
+      numericFieldMap.put(type.name(), field);
+      doc.add(field);
+    }
+    
+    numericConfigMap.put(DATE_FIELD_NAME, new LegacyNumericConfig(PRECISION_STEP,
+        DATE_FORMAT, LegacyNumericType.LONG));
+    FieldType ft = new FieldType(LegacyLongField.TYPE_NOT_STORED);
+    ft.setStored(true);
+    ft.setNumericPrecisionStep(PRECISION_STEP);
+    LegacyLongField dateField = new LegacyLongField(DATE_FIELD_NAME, 0l, ft);
+    numericFieldMap.put(DATE_FIELD_NAME, dateField);
+    doc.add(dateField);
+    
+    for (NumberType numberType : NumberType.values()) {
+      setFieldValues(numberType, numericFieldMap);
+      if (VERBOSE) System.out.println("Indexing document: " + doc);
+      writer.addDocument(doc);
+    }
+    
+    reader = writer.getReader();
+    searcher = newSearcher(reader);
+    writer.close();
+    
+  }
+  
+  private static Number getNumberType(NumberType numberType, String fieldName) {
+    
+    if (numberType == null) {
+      return null;
+    }
+    
+    switch (numberType) {
+      
+      case POSITIVE:
+        return RANDOM_NUMBER_MAP.get(fieldName);
+        
+      case NEGATIVE:
+        Number number = RANDOM_NUMBER_MAP.get(fieldName);
+        
+        if (LegacyNumericType.LONG.name().equals(fieldName)
+            || DATE_FIELD_NAME.equals(fieldName)) {
+          number = -number.longValue();
+          
+        } else if (FieldType.LegacyNumericType.DOUBLE.name().equals(fieldName)) {
+          number = -number.doubleValue();
+          
+        } else if (FieldType.LegacyNumericType.FLOAT.name().equals(fieldName)) {
+          number = -number.floatValue();
+          
+        } else if (LegacyNumericType.INT.name().equals(fieldName)) {
+          number = -number.intValue();
+          
+        } else {
+          throw new IllegalArgumentException("field name not found: "
+              + fieldName);
+        }
+        
+        return number;
+        
+      default:
+        return 0;
+        
+    }
+    
+  }
+  
+  private static void setFieldValues(NumberType numberType,
+      HashMap<String,Field> numericFieldMap) {
+    
+    Number number = getNumberType(numberType, LegacyNumericType.DOUBLE
+        .name());
+    numericFieldMap.get(LegacyNumericType.DOUBLE.name()).setDoubleValue(
+        number.doubleValue());
+    
+    number = getNumberType(numberType, FieldType.LegacyNumericType.INT.name());
+    numericFieldMap.get(FieldType.LegacyNumericType.INT.name()).setIntValue(
+        number.intValue());
+    
+    number = getNumberType(numberType, LegacyNumericType.LONG.name());
+    numericFieldMap.get(FieldType.LegacyNumericType.LONG.name()).setLongValue(
+        number.longValue());
+    
+    number = getNumberType(numberType, FieldType.LegacyNumericType.FLOAT.name());
+    numericFieldMap.get(FieldType.LegacyNumericType.FLOAT.name()).setFloatValue(
+        number.floatValue());
+    
+    number = getNumberType(numberType, DATE_FIELD_NAME);
+    numericFieldMap.get(DATE_FIELD_NAME).setLongValue(number.longValue());
+  }
+  
+  private static int randomDateStyle(Random random) {
+    return DATE_STYLES[random.nextInt(DATE_STYLES.length)];
+  }
+  
+  @Test
+  public void testInclusiveNumericRange() throws Exception {
+    assertRangeQuery(NumberType.ZERO, NumberType.ZERO, true, true, 1);
+    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, true, 2);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, true, 2);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, true, 3);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, true, 1);
+  }
+  
+   @Test
+  // test disabled since standard syntax parser does not work with inclusive and
+  // exclusive at the same time
+  public void testInclusiveLowerNumericRange() throws Exception {
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, true, 1);
+    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, true, 1);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, true, 2);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, true, 0);
+   }
+  
+  @Test
+  // test disabled since standard syntax parser does not work with inclusive and
+  // exclusive at the same time
+  public void testInclusiveUpperNumericRange() throws Exception {
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, false, 1);
+    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, false, 1);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, false, 2);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, false, 0);
+  }
+  
+  @Test
+  public void testExclusiveNumericRange() throws Exception {
+    assertRangeQuery(NumberType.ZERO, NumberType.ZERO, false, false, 0);
+    assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, false, 0);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, false, 0);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, false, 1);
+    assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, false, 0);
+  }
+  
+  @Test
+  public void testOpenRangeNumericQuery() throws Exception {
+    assertOpenRangeQuery(NumberType.ZERO, "<", 1);
+    assertOpenRangeQuery(NumberType.POSITIVE, "<", 2);
+    assertOpenRangeQuery(NumberType.NEGATIVE, "<", 0);
+    
+    assertOpenRangeQuery(NumberType.ZERO, "<=", 2);
+    assertOpenRangeQuery(NumberType.POSITIVE, "<=", 3);
+    assertOpenRangeQuery(NumberType.NEGATIVE, "<=", 1);
+    
+    assertOpenRangeQuery(NumberType.ZERO, ">", 1);
+    assertOpenRangeQuery(NumberType.POSITIVE, ">", 0);
+    assertOpenRangeQuery(NumberType.NEGATIVE, ">", 2);
+    
+    assertOpenRangeQuery(NumberType.ZERO, ">=", 2);
+    assertOpenRangeQuery(NumberType.POSITIVE, ">=", 1);
+    assertOpenRangeQuery(NumberType.NEGATIVE, ">=", 3);
+    
+    assertOpenRangeQuery(NumberType.NEGATIVE, "=", 1);
+    assertOpenRangeQuery(NumberType.ZERO, "=", 1);
+    assertOpenRangeQuery(NumberType.POSITIVE, "=", 1);
+    
+    assertRangeQuery(NumberType.NEGATIVE, null, true, true, 3);
+    assertRangeQuery(NumberType.NEGATIVE, null, false, true, 2);
+    assertRangeQuery(NumberType.POSITIVE, null, true, false, 1);
+    assertRangeQuery(NumberType.ZERO, null, false, false, 1);
+
+    assertRangeQuery(null, NumberType.POSITIVE, true, true, 3);
+    assertRangeQuery(null, NumberType.POSITIVE, true, false, 2);
+    assertRangeQuery(null, NumberType.NEGATIVE, false, true, 1);
+    assertRangeQuery(null, NumberType.ZERO, false, false, 1);
+    
+    assertRangeQuery(null, null, false, false, 3);
+    assertRangeQuery(null, null, true, true, 3);
+    
+  }
+  
+  @Test
+  public void testSimpleNumericQuery() throws Exception {
+    assertSimpleQuery(NumberType.ZERO, 1);
+    assertSimpleQuery(NumberType.POSITIVE, 1);
+    assertSimpleQuery(NumberType.NEGATIVE, 1);
+  }
+  
+  public void assertRangeQuery(NumberType lowerType, NumberType upperType,
+      boolean lowerInclusive, boolean upperInclusive, int expectedDocCount)
+      throws QueryNodeException, IOException {
+    
+    StringBuilder sb = new StringBuilder();
+    
+    String lowerInclusiveStr = (lowerInclusive ? "[" : "{");
+    String upperInclusiveStr = (upperInclusive ? "]" : "}");
+    
+    for (LegacyNumericType type : LegacyNumericType.values()) {
+      String lowerStr = numberToString(getNumberType(lowerType, type.name()));
+      String upperStr = numberToString(getNumberType(upperType, type.name()));
+      
+      sb.append("+").append(type.name()).append(':').append(lowerInclusiveStr)
+          .append('"').append(lowerStr).append("\" TO \"").append(upperStr)
+          .append('"').append(upperInclusiveStr).append(' ');
+    }
+    
+    Number lowerDateNumber = getNumberType(lowerType, DATE_FIELD_NAME);
+    Number upperDateNumber = getNumberType(upperType, DATE_FIELD_NAME);
+    String lowerDateStr;
+    String upperDateStr;
+    
+    if (lowerDateNumber != null) {
+      lowerDateStr = ESCAPER.escape(
+          DATE_FORMAT.format(new Date(lowerDateNumber.longValue())), LOCALE,
+          EscapeQuerySyntax.Type.STRING).toString();
+      
+    } else {
+      lowerDateStr = "*";
+    }
+    
+    if (upperDateNumber != null) {
+    upperDateStr = ESCAPER.escape(
+          DATE_FORMAT.format(new Date(upperDateNumber.longValue())), LOCALE,
+          EscapeQuerySyntax.Type.STRING).toString();
+    
+    } else {
+      upperDateStr = "*";
+    }
+    
+    sb.append("+").append(DATE_FIELD_NAME).append(':')
+        .append(lowerInclusiveStr).append('"').append(lowerDateStr).append(
+            "\" TO \"").append(upperDateStr).append('"').append(
+            upperInclusiveStr);
+    
+    testQuery(sb.toString(), expectedDocCount);
+    
+  }
+  
+  public void assertOpenRangeQuery(NumberType boundType, String operator, int expectedDocCount)
+      throws QueryNodeException, IOException {
+
+    StringBuilder sb = new StringBuilder();
+    
+    for (LegacyNumericType type : FieldType.LegacyNumericType.values()) {
+      String boundStr = numberToString(getNumberType(boundType, type.name()));
+      
+      sb.append("+").append(type.name()).append(operator).append('"').append(boundStr).append('"').append(' ');
+    }
+    
+    String boundDateStr = ESCAPER.escape(
+        DATE_FORMAT.format(new Date(getNumberType(boundType, DATE_FIELD_NAME)
+            .longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
+    
+    sb.append("+").append(DATE_FIELD_NAME).append(operator).append('"').append(boundDateStr).append('"');
+    
+    testQuery(sb.toString(), expectedDocCount);
+  }
+  
+  public void assertSimpleQuery(NumberType numberType, int expectedDocCount)
+      throws QueryNodeException, IOException {
+    StringBuilder sb = new StringBuilder();
+    
+    for (LegacyNumericType type : LegacyNumericType.values()) {
+      String numberStr = numberToString(getNumberType(numberType, type.name()));
+      sb.append('+').append(type.name()).append(":\"").append(numberStr)
+          .append("\" ");
+    }
+    
+    String dateStr = ESCAPER.escape(
+        DATE_FORMAT.format(new Date(getNumberType(numberType, DATE_FIELD_NAME)
+            .longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
+    
+    sb.append('+').append(DATE_FIELD_NAME).append(":\"").append(dateStr)
+        .append('"');
+    
+    testQuery(sb.toString(), expectedDocCount);
+    
+  }
+  
+  private void testQuery(String queryStr, int expectedDocCount)
+      throws QueryNodeException, IOException {
+    if (VERBOSE) System.out.println("Parsing: " + queryStr);
+    
+    Query query = qp.parse(queryStr, FIELD_NAME);
+    if (VERBOSE) System.out.println("Querying: " + query);
+    TopDocs topDocs = searcher.search(query, 1000);
+    
+    String msg = "Query <" + queryStr + "> retrieved " + topDocs.totalHits
+        + " document(s), " + expectedDocCount + " document(s) expected.";
+    
+    if (VERBOSE) System.out.println(msg);
+    
+    assertEquals(msg, expectedDocCount, topDocs.totalHits);
+  }
+  
+  private static String numberToString(Number number) {
+    return number == null ? "*" : ESCAPER.escape(NUMBER_FORMAT.format(number),
+        LOCALE, EscapeQuerySyntax.Type.STRING).toString();
+  }
+  
+  private static Number normalizeNumber(Number number) throws ParseException {
+    return NUMBER_FORMAT.parse(NUMBER_FORMAT.format(number));
+  }
+  
+  @AfterClass
+  public static void afterClass() throws Exception {
+    searcher = null;
+    reader.close();
+    reader = null;
+    directory.close();
+    directory = null;
+    qp = null;
+    LOCALE = null;
+    TIMEZONE = null;
+    NUMBER_FORMAT = null;
+    DATE_FORMAT = null;
+    ESCAPER = null;
+  }
+  
+}