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/08/17 13:29:58 UTC

[7/7] lucene-solr:master: LUCENE-7413: move legacy numeric support to backwards module

LUCENE-7413: move legacy numeric support to backwards module


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

Branch: refs/heads/master
Commit: 105c7eae87896762cbcb295c73c8e8b1fd8f71f8
Parents: ba09fa7
Author: Robert Muir <rm...@apache.org>
Authored: Wed Aug 17 09:28:45 2016 -0400
Committer: Robert Muir <rm...@apache.org>
Committed: Wed Aug 17 09:28:45 2016 -0400

----------------------------------------------------------------------
 .../apache/lucene/legacy/LegacyDoubleField.java | 174 ++++++
 .../org/apache/lucene/legacy/LegacyField.java   |  90 +++
 .../apache/lucene/legacy/LegacyFieldType.java   | 149 +++++
 .../apache/lucene/legacy/LegacyFloatField.java  | 174 ++++++
 .../apache/lucene/legacy/LegacyIntField.java    | 175 ++++++
 .../apache/lucene/legacy/LegacyLongField.java   | 184 ++++++
 .../lucene/legacy/LegacyNumericRangeQuery.java  | 537 ++++++++++++++++
 .../lucene/legacy/LegacyNumericTokenStream.java | 357 +++++++++++
 .../apache/lucene/legacy/LegacyNumericType.java |  34 +
 .../lucene/legacy/LegacyNumericUtils.java       | 510 +++++++++++++++
 .../org/apache/lucene/legacy/package-info.java  |  21 +
 .../index/TestBackwardsCompatibility.java       |   8 +-
 .../apache/lucene/legacy/TestLegacyField.java   | 196 ++++++
 .../lucene/legacy/TestLegacyFieldReuse.java     |  81 +++
 .../lucene/legacy/TestLegacyNumericUtils.java   | 571 +++++++++++++++++
 .../apache/lucene/legacy/TestLegacyTerms.java   | 164 +++++
 .../TestMultiValuedNumericRangeQuery.java       |  84 +++
 .../lucene/legacy/TestNumericRangeQuery32.java  | 461 ++++++++++++++
 .../lucene/legacy/TestNumericRangeQuery64.java  | 490 +++++++++++++++
 .../lucene/legacy/TestNumericTokenStream.java   | 188 ++++++
 .../analysis/LegacyNumericTokenStream.java      | 357 -----------
 .../java/org/apache/lucene/document/Field.java  |  33 -
 .../org/apache/lucene/document/FieldType.java   |  98 +--
 .../lucene/document/LegacyDoubleField.java      | 172 -----
 .../lucene/document/LegacyFloatField.java       | 174 ------
 .../apache/lucene/document/LegacyIntField.java  | 174 ------
 .../apache/lucene/document/LegacyLongField.java | 182 ------
 .../lucene/search/LegacyNumericRangeQuery.java  | 536 ----------------
 .../apache/lucene/util/LegacyNumericUtils.java  | 508 ---------------
 .../lucene/analysis/TestNumericTokenStream.java | 169 -----
 .../org/apache/lucene/document/TestField.java   |  94 ---
 .../apache/lucene/document/TestFieldType.java   |   9 -
 .../org/apache/lucene/index/TestFieldReuse.java |  53 +-
 .../test/org/apache/lucene/index/TestTerms.java | 134 ----
 .../TestMultiValuedNumericRangeQuery.java       |  80 ---
 .../lucene/search/TestNumericRangeQuery32.java  | 589 ------------------
 .../lucene/search/TestNumericRangeQuery64.java  | 623 -------------------
 .../lucene/util/TestLegacyNumericUtils.java     | 564 -----------------
 lucene/join/build.xml                           |   6 +-
 .../search/join/DocValuesTermsCollector.java    |   9 +-
 .../org/apache/lucene/search/join/JoinUtil.java |   6 +-
 .../search/join/TermsIncludingScoreQuery.java   |   2 +-
 .../apache/lucene/search/join/TestJoinUtil.java |   6 +-
 .../memory/TestMemoryIndexAgainstRAMDir.java    |   7 -
 .../search/TestDiversifiedTopDocsCollector.java |   5 +-
 lucene/queryparser/build.xml                    |   6 +-
 .../LegacyNumericRangeQueryNodeBuilder.java     |  10 +-
 .../standard/config/LegacyNumericConfig.java    |  15 +-
 .../nodes/LegacyNumericRangeQueryNode.java      |   9 +-
 .../LegacyNumericRangeQueryBuilder.java         |   8 +-
 .../standard/TestLegacyNumericQueryParser.java  |  34 +-
 .../xml/CoreParserTestIndexData.java            |   2 +-
 .../builders/TestNumericRangeQueryBuilder.java  |   2 +-
 lucene/spatial-extras/build.xml                 |   8 +-
 .../lucene/spatial/bbox/BBoxStrategy.java       |  39 +-
 .../prefix/BytesRefIteratorTokenStream.java     |   2 +-
 .../spatial/vector/PointVectorStrategy.java     |  37 +-
 .../lucene/spatial/bbox/TestBBoxStrategy.java   |   8 +-
 .../solr/analytics/util/AnalyticsParsers.java   |   2 +-
 .../util/valuesource/DateFieldSource.java       |   2 +-
 .../solr/handler/component/StatsField.java      |  17 +-
 .../org/apache/solr/request/IntervalFacets.java |   2 +-
 .../org/apache/solr/request/NumericFacets.java  |   3 +-
 .../java/org/apache/solr/schema/BBoxField.java  |   7 +-
 .../java/org/apache/solr/schema/EnumField.java  |  17 +-
 .../java/org/apache/solr/schema/FieldType.java  |   3 +-
 .../schema/SpatialPointVectorFieldType.java     |   9 +-
 .../org/apache/solr/schema/TrieDoubleField.java |   2 +-
 .../java/org/apache/solr/schema/TrieField.java  |  44 +-
 .../org/apache/solr/schema/TrieFloatField.java  |   2 +-
 .../org/apache/solr/schema/TrieIntField.java    |   2 +-
 .../org/apache/solr/schema/TrieLongField.java   |   2 +-
 .../org/apache/solr/search/QueryParsing.java    |   2 +-
 .../apache/solr/search/QueryWrapperFilter.java  |   2 +-
 .../apache/solr/search/facet/FacetField.java    |   3 +-
 .../apache/solr/search/mlt/CloudMLTQParser.java |   2 +-
 .../solr/search/mlt/SimpleMLTQParser.java       |   2 +-
 .../org/apache/solr/uninverting/FieldCache.java |  20 +-
 .../solr/uninverting/UninvertingReader.java     |  16 +-
 .../org/apache/solr/update/VersionInfo.java     |   2 +-
 .../solr/search/TestMaxScoreQueryParser.java    |   1 +
 .../solr/search/function/TestOrdValues.java     |   4 +-
 .../solr/uninverting/TestDocTermOrds.java       |   6 +-
 .../TestFieldCacheSanityChecker.java            |   8 +-
 .../solr/uninverting/TestFieldCacheSort.java    |   8 +-
 .../solr/uninverting/TestLegacyFieldCache.java  |  10 +-
 .../solr/uninverting/TestNumericTerms32.java    |  14 +-
 .../solr/uninverting/TestNumericTerms64.java    |  16 +-
 .../solr/uninverting/TestUninvertingReader.java |  10 +-
 89 files changed, 4885 insertions(+), 4773 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyDoubleField.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyDoubleField.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyDoubleField.java
new file mode 100644
index 0000000..e98a4f0
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyDoubleField.java
@@ -0,0 +1,174 @@
+/*
+ * 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.legacy;
+
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.index.IndexOptions;
+
+
+/**
+ * <p>
+ * Field that indexes <code>double</code> values
+ * for efficient range filtering and sorting. Here's an example usage:
+ * 
+ * <pre class="prettyprint">
+ * document.add(new LegacyDoubleField(name, 6.0, Field.Store.NO));
+ * </pre>
+ * 
+ * For optimal performance, re-use the <code>LegacyDoubleField</code> and
+ * {@link Document} instance for more than one document:
+ * 
+ * <pre class="prettyprint">
+ *  LegacyDoubleField field = new LegacyDoubleField(name, 0.0, Field.Store.NO);
+ *  Document document = new Document();
+ *  document.add(field);
+ * 
+ *  for(all documents) {
+ *    ...
+ *    field.setDoubleValue(value)
+ *    writer.addDocument(document);
+ *    ...
+ *  }
+ * </pre>
+ *
+ * See also {@link LegacyIntField}, {@link LegacyLongField}, {@link
+ * LegacyFloatField}.
+ *
+ * <p>To perform range querying or filtering against a
+ * <code>LegacyDoubleField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * To sort according to a
+ * <code>LegacyDoubleField</code>, use the normal numeric sort types, eg
+ * {@link org.apache.lucene.search.SortField.Type#DOUBLE}. <code>LegacyDoubleField</code>
+ * values can also be loaded directly from {@link org.apache.lucene.index.LeafReader#getNumericDocValues}.</p>
+ *
+ * <p>You may add the same field name as an <code>LegacyDoubleField</code> to
+ * the same document more than once.  Range querying and
+ * filtering will be the logical OR of all values; so a range query
+ * will hit all documents that have at least one value in
+ * the range. However sort behavior is not defined.  If you need to sort,
+ * you should separately index a single-valued <code>LegacyDoubleField</code>.</p>
+ *
+ * <p>A <code>LegacyDoubleField</code> will consume somewhat more disk space
+ * in the index than an ordinary single-valued field.
+ * However, for a typical index that includes substantial
+ * textual content per document, this increase will likely
+ * be in the noise. </p>
+ *
+ * <p>Within Lucene, each numeric value is indexed as a
+ * <em>trie</em> structure, where each term is logically
+ * assigned to larger and larger pre-defined brackets (which
+ * are simply lower-precision representations of the value).
+ * The step size between each successive bracket is called the
+ * <code>precisionStep</code>, measured in bits.  Smaller
+ * <code>precisionStep</code> values result in larger number
+ * of brackets, which consumes more disk space in the index
+ * but may result in faster range search performance.  The
+ * default value, 16, was selected for a reasonable tradeoff
+ * of disk space consumption versus performance.  You can
+ * create a custom {@link LegacyFieldType} and invoke the {@link
+ * LegacyFieldType#setNumericPrecisionStep} method if you'd
+ * like to change the value.  Note that you must also
+ * specify a congruent value when creating {@link
+ * org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * For low cardinality fields larger precision steps are good.
+ * If the cardinality is &lt; 100, it is fair
+ * to use {@link Integer#MAX_VALUE}, which produces one
+ * term per value.
+ *
+ * <p>For more information on the internals of numeric trie
+ * indexing, including the <a
+ * href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
+ * configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
+ * indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
+ *
+ * <p>If you only need to sort by numeric value, and never
+ * run range querying/filtering, you can index using a
+ * <code>precisionStep</code> of {@link Integer#MAX_VALUE}.
+ * This will minimize disk space consumed. </p>
+ *
+ * <p>More advanced users can instead use {@link
+ * org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
+ * class is a wrapper around this token stream type for
+ * easier, more intuitive usage.</p>
+ *
+ * @deprecated Please use {@link DoublePoint} instead
+ *
+ * @since 2.9
+ */
+
+@Deprecated
+public final class LegacyDoubleField extends LegacyField {
+  
+  /** 
+   * Type for a LegacyDoubleField that is not stored:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_NOT_STORED = new LegacyFieldType();
+  static {
+    TYPE_NOT_STORED.setTokenized(true);
+    TYPE_NOT_STORED.setOmitNorms(true);
+    TYPE_NOT_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_NOT_STORED.setNumericType(LegacyNumericType.DOUBLE);
+    TYPE_NOT_STORED.freeze();
+  }
+
+  /** 
+   * Type for a stored LegacyDoubleField:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_STORED = new LegacyFieldType();
+  static {
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_STORED.setNumericType(LegacyNumericType.DOUBLE);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.freeze();
+  }
+
+  /** Creates a stored or un-stored LegacyDoubleField with the provided value
+   *  and default <code>precisionStep</code> {@link
+   *  org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
+   *  @param name field name
+   *  @param value 64-bit double value
+   *  @param stored Store.YES if the content should also be stored
+   *  @throws IllegalArgumentException if the field name is null. 
+   */
+  public LegacyDoubleField(String name, double value, Store stored) {
+    super(name, stored == Store.YES ? TYPE_STORED : TYPE_NOT_STORED);
+    fieldsData = Double.valueOf(value);
+  }
+  
+  /** Expert: allows you to customize the {@link
+   *  LegacyFieldType}. 
+   *  @param name field name
+   *  @param value 64-bit double value
+   *  @param type customized field type: must have {@link LegacyFieldType#numericType()}
+   *         of {@link LegacyNumericType#DOUBLE}.
+   *  @throws IllegalArgumentException if the field name or type is null, or
+   *          if the field type does not have a DOUBLE numericType()
+   */
+  public LegacyDoubleField(String name, double value, LegacyFieldType type) {
+    super(name, type);
+    if (type.numericType() != LegacyNumericType.DOUBLE) {
+      throw new IllegalArgumentException("type.numericType() must be DOUBLE but got " + type.numericType());
+    }
+    fieldsData = Double.valueOf(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyField.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyField.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyField.java
new file mode 100644
index 0000000..87ac0e5
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyField.java
@@ -0,0 +1,90 @@
+/*
+ * 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.legacy;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexOptions;
+
+/**
+ * Field extension with support for legacy numerics
+ * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+ */
+@Deprecated
+public class LegacyField extends Field {
+
+  /**
+   * Expert: creates a field with no initial value.
+   * Intended only for custom LegacyField subclasses.
+   * @param name field name
+   * @param type field type
+   * @throws IllegalArgumentException if either the name or type
+   *         is null.
+   */
+  public LegacyField(String name, LegacyFieldType type) {
+    super(name, type);
+  }
+  
+  @Override
+  public TokenStream tokenStream(Analyzer analyzer, TokenStream reuse) {
+    if (fieldType().indexOptions() == IndexOptions.NONE) {
+      // Not indexed
+      return null;
+    }
+    final LegacyFieldType fieldType = (LegacyFieldType) fieldType();
+    final LegacyNumericType numericType = fieldType.numericType();
+    if (numericType != null) {
+      if (!(reuse instanceof LegacyNumericTokenStream && ((LegacyNumericTokenStream)reuse).getPrecisionStep() == fieldType.numericPrecisionStep())) {
+        // lazy init the TokenStream as it is heavy to instantiate
+        // (attributes,...) if not needed (stored field loading)
+        reuse = new LegacyNumericTokenStream(fieldType.numericPrecisionStep());
+      }
+      final LegacyNumericTokenStream nts = (LegacyNumericTokenStream) reuse;
+      // initialize value in TokenStream
+      final Number val = (Number) fieldsData;
+      switch (numericType) {
+      case INT:
+        nts.setIntValue(val.intValue());
+        break;
+      case LONG:
+        nts.setLongValue(val.longValue());
+        break;
+      case FLOAT:
+        nts.setFloatValue(val.floatValue());
+        break;
+      case DOUBLE:
+        nts.setDoubleValue(val.doubleValue());
+        break;
+      default:
+        throw new AssertionError("Should never get here");
+      }
+      return reuse;
+    }
+    return super.tokenStream(analyzer, reuse);
+  }
+  
+  @Override
+  public void setTokenStream(TokenStream tokenStream) {
+    final LegacyFieldType fieldType = (LegacyFieldType) fieldType();
+    if (fieldType.numericType() != null) {
+      throw new IllegalArgumentException("cannot set private TokenStream on numeric fields");
+    }
+    super.setTokenStream(tokenStream);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFieldType.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFieldType.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFieldType.java
new file mode 100644
index 0000000..1f4b0af
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFieldType.java
@@ -0,0 +1,149 @@
+/*
+ * 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.legacy;
+
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.IndexOptions;
+
+/**
+ * FieldType extension with support for legacy numerics
+ * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+ */
+@Deprecated
+public final class LegacyFieldType extends FieldType {
+  private LegacyNumericType numericType;
+  private int numericPrecisionStep = LegacyNumericUtils.PRECISION_STEP_DEFAULT;
+
+  /**
+   * Create a new mutable LegacyFieldType with all of the properties from <code>ref</code>
+   */
+  public LegacyFieldType(LegacyFieldType ref) {
+    super(ref);
+    this.numericType = ref.numericType;
+    this.numericPrecisionStep = ref.numericPrecisionStep;
+  }
+  
+  /**
+   * Create a new FieldType with default properties.
+   */
+  public LegacyFieldType() {
+  }
+  
+  /**
+   * Specifies the field's numeric type.
+   * @param type numeric type, or null if the field has no numeric type.
+   * @throws IllegalStateException if this FieldType is frozen against
+   *         future modifications.
+   * @see #numericType()
+   *
+   * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+   */
+  @Deprecated
+  public void setNumericType(LegacyNumericType type) {
+    checkIfFrozen();
+    numericType = type;
+  }
+  
+  /** 
+   * LegacyNumericType: if non-null then the field's value will be indexed
+   * numerically so that {@link org.apache.lucene.legacy.LegacyNumericRangeQuery} can be used at
+   * search time. 
+   * <p>
+   * The default is <code>null</code> (no numeric type) 
+   * @see #setNumericType(LegacyNumericType)
+   *
+   * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+   */
+  @Deprecated
+  public LegacyNumericType numericType() {
+    return numericType;
+  }
+  
+  /**
+   * Sets the numeric precision step for the field.
+   * @param precisionStep numeric precision step for the field
+   * @throws IllegalArgumentException if precisionStep is less than 1. 
+   * @throws IllegalStateException if this FieldType is frozen against
+   *         future modifications.
+   * @see #numericPrecisionStep()
+   *
+   * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+   */
+  @Deprecated
+  public void setNumericPrecisionStep(int precisionStep) {
+    checkIfFrozen();
+    if (precisionStep < 1) {
+      throw new IllegalArgumentException("precisionStep must be >= 1 (got " + precisionStep + ")");
+    }
+    this.numericPrecisionStep = precisionStep;
+  }
+  
+  /** 
+   * Precision step for numeric field. 
+   * <p>
+   * This has no effect if {@link #numericType()} returns null.
+   * <p>
+   * The default is {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT}
+   * @see #setNumericPrecisionStep(int)
+   *
+   * @deprecated Please switch to {@link org.apache.lucene.index.PointValues} instead
+   */
+  @Deprecated
+  public int numericPrecisionStep() {
+    return numericPrecisionStep;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = super.hashCode();
+    result = prime * result + numericPrecisionStep;
+    result = prime * result + ((numericType == null) ? 0 : numericType.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!super.equals(obj)) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) return false;
+    LegacyFieldType other = (LegacyFieldType) obj;
+    if (numericPrecisionStep != other.numericPrecisionStep) return false;
+    if (numericType != other.numericType) return false;
+    return true;
+  }
+
+  /** Prints a Field for human consumption. */
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(super.toString());
+    if (indexOptions() != IndexOptions.NONE) {
+      if (result.length() > 0) {
+        result.append(",");
+      }
+      if (numericType != null) {
+        result.append(",numericType=");
+        result.append(numericType);
+        result.append(",numericPrecisionStep=");
+        result.append(numericPrecisionStep);
+      }
+    }
+    return result.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFloatField.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFloatField.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFloatField.java
new file mode 100644
index 0000000..ea3b84a
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyFloatField.java
@@ -0,0 +1,174 @@
+/*
+ * 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.legacy;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.index.IndexOptions;
+
+/**
+ * <p>
+ * Field that indexes <code>float</code> values
+ * for efficient range filtering and sorting. Here's an example usage:
+ * 
+ * <pre class="prettyprint">
+ * document.add(new LegacyFloatField(name, 6.0F, Field.Store.NO));
+ * </pre>
+ * 
+ * For optimal performance, re-use the <code>LegacyFloatField</code> and
+ * {@link Document} instance for more than one document:
+ * 
+ * <pre class="prettyprint">
+ *  LegacyFloatField field = new LegacyFloatField(name, 0.0F, Field.Store.NO);
+ *  Document document = new Document();
+ *  document.add(field);
+ * 
+ *  for(all documents) {
+ *    ...
+ *    field.setFloatValue(value)
+ *    writer.addDocument(document);
+ *    ...
+ *  }
+ * </pre>
+ *
+ * See also {@link LegacyIntField}, {@link LegacyLongField}, {@link
+ * LegacyDoubleField}.
+ *
+ * <p>To perform range querying or filtering against a
+ * <code>LegacyFloatField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * To sort according to a
+ * <code>LegacyFloatField</code>, use the normal numeric sort types, eg
+ * {@link org.apache.lucene.search.SortField.Type#FLOAT}. <code>LegacyFloatField</code>
+ * values can also be loaded directly from {@link org.apache.lucene.index.LeafReader#getNumericDocValues}.</p>
+ *
+ * <p>You may add the same field name as an <code>LegacyFloatField</code> to
+ * the same document more than once.  Range querying and
+ * filtering will be the logical OR of all values; so a range query
+ * will hit all documents that have at least one value in
+ * the range. However sort behavior is not defined.  If you need to sort,
+ * you should separately index a single-valued <code>LegacyFloatField</code>.</p>
+ *
+ * <p>A <code>LegacyFloatField</code> will consume somewhat more disk space
+ * in the index than an ordinary single-valued field.
+ * However, for a typical index that includes substantial
+ * textual content per document, this increase will likely
+ * be in the noise. </p>
+ *
+ * <p>Within Lucene, each numeric value is indexed as a
+ * <em>trie</em> structure, where each term is logically
+ * assigned to larger and larger pre-defined brackets (which
+ * are simply lower-precision representations of the value).
+ * The step size between each successive bracket is called the
+ * <code>precisionStep</code>, measured in bits.  Smaller
+ * <code>precisionStep</code> values result in larger number
+ * of brackets, which consumes more disk space in the index
+ * but may result in faster range search performance.  The
+ * default value, 8, was selected for a reasonable tradeoff
+ * of disk space consumption versus performance.  You can
+ * create a custom {@link LegacyFieldType} and invoke the {@link
+ * LegacyFieldType#setNumericPrecisionStep} method if you'd
+ * like to change the value.  Note that you must also
+ * specify a congruent value when creating {@link
+ * org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * For low cardinality fields larger precision steps are good.
+ * If the cardinality is &lt; 100, it is fair
+ * to use {@link Integer#MAX_VALUE}, which produces one
+ * term per value.
+ *
+ * <p>For more information on the internals of numeric trie
+ * indexing, including the <a
+ * href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
+ * configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
+ * indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
+ *
+ * <p>If you only need to sort by numeric value, and never
+ * run range querying/filtering, you can index using a
+ * <code>precisionStep</code> of {@link Integer#MAX_VALUE}.
+ * This will minimize disk space consumed. </p>
+ *
+ * <p>More advanced users can instead use {@link
+ * org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
+ * class is a wrapper around this token stream type for
+ * easier, more intuitive usage.</p>
+ *
+ * @deprecated Please use {@link FloatPoint} instead
+ *
+ * @since 2.9
+ */
+
+@Deprecated
+public final class LegacyFloatField extends LegacyField {
+  
+  /** 
+   * Type for a LegacyFloatField that is not stored:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_NOT_STORED = new LegacyFieldType();
+  static {
+    TYPE_NOT_STORED.setTokenized(true);
+    TYPE_NOT_STORED.setOmitNorms(true);
+    TYPE_NOT_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_NOT_STORED.setNumericType(LegacyNumericType.FLOAT);
+    TYPE_NOT_STORED.setNumericPrecisionStep(LegacyNumericUtils.PRECISION_STEP_DEFAULT_32);
+    TYPE_NOT_STORED.freeze();
+  }
+
+  /** 
+   * Type for a stored LegacyFloatField:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_STORED = new LegacyFieldType();
+  static {
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_STORED.setNumericType(LegacyNumericType.FLOAT);
+    TYPE_STORED.setNumericPrecisionStep(LegacyNumericUtils.PRECISION_STEP_DEFAULT_32);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.freeze();
+  }
+
+  /** Creates a stored or un-stored LegacyFloatField with the provided value
+   *  and default <code>precisionStep</code> {@link
+   *  org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
+   *  @param name field name
+   *  @param value 32-bit double value
+   *  @param stored Store.YES if the content should also be stored
+   *  @throws IllegalArgumentException if the field name is null.
+   */
+  public LegacyFloatField(String name, float value, Store stored) {
+    super(name, stored == Store.YES ? TYPE_STORED : TYPE_NOT_STORED);
+    fieldsData = Float.valueOf(value);
+  }
+  
+  /** Expert: allows you to customize the {@link
+   *  LegacyFieldType}. 
+   *  @param name field name
+   *  @param value 32-bit float value
+   *  @param type customized field type: must have {@link LegacyFieldType#numericType()}
+   *         of {@link LegacyNumericType#FLOAT}.
+   *  @throws IllegalArgumentException if the field name or type is null, or
+   *          if the field type does not have a FLOAT numericType()
+   */
+  public LegacyFloatField(String name, float value, LegacyFieldType type) {
+    super(name, type);
+    if (type.numericType() != LegacyNumericType.FLOAT) {
+      throw new IllegalArgumentException("type.numericType() must be FLOAT but got " + type.numericType());
+    }
+    fieldsData = Float.valueOf(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyIntField.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyIntField.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyIntField.java
new file mode 100644
index 0000000..e3ae965
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyIntField.java
@@ -0,0 +1,175 @@
+/*
+ * 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.legacy;
+
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.index.IndexOptions;
+
+/**
+ * <p>
+ * Field that indexes <code>int</code> values
+ * for efficient range filtering and sorting. Here's an example usage:
+ * 
+ * <pre class="prettyprint">
+ * document.add(new LegacyIntField(name, 6, Field.Store.NO));
+ * </pre>
+ * 
+ * For optimal performance, re-use the <code>LegacyIntField</code> and
+ * {@link Document} instance for more than one document:
+ * 
+ * <pre class="prettyprint">
+ *  LegacyIntField field = new LegacyIntField(name, 6, Field.Store.NO);
+ *  Document document = new Document();
+ *  document.add(field);
+ * 
+ *  for(all documents) {
+ *    ...
+ *    field.setIntValue(value)
+ *    writer.addDocument(document);
+ *    ...
+ *  }
+ * </pre>
+ *
+ * See also {@link LegacyLongField}, {@link LegacyFloatField}, {@link
+ * LegacyDoubleField}.
+ *
+ * <p>To perform range querying or filtering against a
+ * <code>LegacyIntField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * To sort according to a
+ * <code>LegacyIntField</code>, use the normal numeric sort types, eg
+ * {@link org.apache.lucene.search.SortField.Type#INT}. <code>LegacyIntField</code>
+ * values can also be loaded directly from {@link org.apache.lucene.index.LeafReader#getNumericDocValues}.</p>
+ *
+ * <p>You may add the same field name as an <code>LegacyIntField</code> to
+ * the same document more than once.  Range querying and
+ * filtering will be the logical OR of all values; so a range query
+ * will hit all documents that have at least one value in
+ * the range. However sort behavior is not defined.  If you need to sort,
+ * you should separately index a single-valued <code>LegacyIntField</code>.</p>
+ *
+ * <p>An <code>LegacyIntField</code> will consume somewhat more disk space
+ * in the index than an ordinary single-valued field.
+ * However, for a typical index that includes substantial
+ * textual content per document, this increase will likely
+ * be in the noise. </p>
+ *
+ * <p>Within Lucene, each numeric value is indexed as a
+ * <em>trie</em> structure, where each term is logically
+ * assigned to larger and larger pre-defined brackets (which
+ * are simply lower-precision representations of the value).
+ * The step size between each successive bracket is called the
+ * <code>precisionStep</code>, measured in bits.  Smaller
+ * <code>precisionStep</code> values result in larger number
+ * of brackets, which consumes more disk space in the index
+ * but may result in faster range search performance.  The
+ * default value, 8, was selected for a reasonable tradeoff
+ * of disk space consumption versus performance.  You can
+ * create a custom {@link LegacyFieldType} and invoke the {@link
+ * LegacyFieldType#setNumericPrecisionStep} method if you'd
+ * like to change the value.  Note that you must also
+ * specify a congruent value when creating {@link
+ * org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * For low cardinality fields larger precision steps are good.
+ * If the cardinality is &lt; 100, it is fair
+ * to use {@link Integer#MAX_VALUE}, which produces one
+ * term per value.
+ *
+ * <p>For more information on the internals of numeric trie
+ * indexing, including the <a
+ * href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
+ * configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
+ * indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
+ *
+ * <p>If you only need to sort by numeric value, and never
+ * run range querying/filtering, you can index using a
+ * <code>precisionStep</code> of {@link Integer#MAX_VALUE}.
+ * This will minimize disk space consumed. </p>
+ *
+ * <p>More advanced users can instead use {@link
+ * org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
+ * class is a wrapper around this token stream type for
+ * easier, more intuitive usage.</p>
+ *
+ * @deprecated Please use {@link IntPoint} instead
+ *
+ * @since 2.9
+ */
+
+@Deprecated
+public final class LegacyIntField extends LegacyField {
+  
+  /** 
+   * Type for an LegacyIntField that is not stored:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_NOT_STORED = new LegacyFieldType();
+  static {
+    TYPE_NOT_STORED.setTokenized(true);
+    TYPE_NOT_STORED.setOmitNorms(true);
+    TYPE_NOT_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_NOT_STORED.setNumericType(LegacyNumericType.INT);
+    TYPE_NOT_STORED.setNumericPrecisionStep(LegacyNumericUtils.PRECISION_STEP_DEFAULT_32);
+    TYPE_NOT_STORED.freeze();
+  }
+
+  /** 
+   * Type for a stored LegacyIntField:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_STORED = new LegacyFieldType();
+  static {
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_STORED.setNumericType(LegacyNumericType.INT);
+    TYPE_STORED.setNumericPrecisionStep(LegacyNumericUtils.PRECISION_STEP_DEFAULT_32);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.freeze();
+  }
+
+  /** Creates a stored or un-stored LegacyIntField with the provided value
+   *  and default <code>precisionStep</code> {@link
+   *  org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
+   *  @param name field name
+   *  @param value 32-bit integer value
+   *  @param stored Store.YES if the content should also be stored
+   *  @throws IllegalArgumentException if the field name is null.
+   */
+  public LegacyIntField(String name, int value, Store stored) {
+    super(name, stored == Store.YES ? TYPE_STORED : TYPE_NOT_STORED);
+    fieldsData = Integer.valueOf(value);
+  }
+  
+  /** Expert: allows you to customize the {@link
+   *  LegacyFieldType}. 
+   *  @param name field name
+   *  @param value 32-bit integer value
+   *  @param type customized field type: must have {@link LegacyFieldType#numericType()}
+   *         of {@link LegacyNumericType#INT}.
+   *  @throws IllegalArgumentException if the field name or type is null, or
+   *          if the field type does not have a INT numericType()
+   */
+  public LegacyIntField(String name, int value, LegacyFieldType type) {
+    super(name, type);
+    if (type.numericType() != LegacyNumericType.INT) {
+      throw new IllegalArgumentException("type.numericType() must be INT but got " + type.numericType());
+    }
+    fieldsData = Integer.valueOf(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyLongField.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyLongField.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyLongField.java
new file mode 100644
index 0000000..3e20b44
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyLongField.java
@@ -0,0 +1,184 @@
+/*
+ * 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.legacy;
+
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.LongPoint;
+import org.apache.lucene.index.IndexOptions;
+
+
+/**
+ * <p>
+ * Field that indexes <code>long</code> values
+ * for efficient range filtering and sorting. Here's an example usage:
+ * 
+ * <pre class="prettyprint">
+ * document.add(new LegacyLongField(name, 6L, Field.Store.NO));
+ * </pre>
+ * 
+ * For optimal performance, re-use the <code>LegacyLongField</code> and
+ * {@link Document} instance for more than one document:
+ * 
+ * <pre class="prettyprint">
+ *  LegacyLongField field = new LegacyLongField(name, 0L, Field.Store.NO);
+ *  Document document = new Document();
+ *  document.add(field);
+ * 
+ *  for(all documents) {
+ *    ...
+ *    field.setLongValue(value)
+ *    writer.addDocument(document);
+ *    ...
+ *  }
+ * </pre>
+ *
+ * See also {@link LegacyIntField}, {@link LegacyFloatField}, {@link
+ * LegacyDoubleField}.
+ *
+ * Any type that can be converted to long can also be
+ * indexed.  For example, date/time values represented by a
+ * {@link java.util.Date} can be translated into a long
+ * value using the {@link java.util.Date#getTime} method.  If you
+ * don't need millisecond precision, you can quantize the
+ * value, either by dividing the result of
+ * {@link java.util.Date#getTime} or using the separate getters
+ * (for year, month, etc.) to construct an <code>int</code> or
+ * <code>long</code> value.
+ *
+ * <p>To perform range querying or filtering against a
+ * <code>LegacyLongField</code>, use {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * To sort according to a
+ * <code>LegacyLongField</code>, use the normal numeric sort types, eg
+ * {@link org.apache.lucene.search.SortField.Type#LONG}. <code>LegacyLongField</code>
+ * values can also be loaded directly from {@link org.apache.lucene.index.LeafReader#getNumericDocValues}.
+ *
+ * <p>You may add the same field name as an <code>LegacyLongField</code> to
+ * the same document more than once.  Range querying and
+ * filtering will be the logical OR of all values; so a range query
+ * will hit all documents that have at least one value in
+ * the range. However sort behavior is not defined.  If you need to sort,
+ * you should separately index a single-valued <code>LegacyLongField</code>.
+ *
+ * <p>A <code>LegacyLongField</code> will consume somewhat more disk space
+ * in the index than an ordinary single-valued field.
+ * However, for a typical index that includes substantial
+ * textual content per document, this increase will likely
+ * be in the noise. </p>
+ *
+ * <p>Within Lucene, each numeric value is indexed as a
+ * <em>trie</em> structure, where each term is logically
+ * assigned to larger and larger pre-defined brackets (which
+ * are simply lower-precision representations of the value).
+ * The step size between each successive bracket is called the
+ * <code>precisionStep</code>, measured in bits.  Smaller
+ * <code>precisionStep</code> values result in larger number
+ * of brackets, which consumes more disk space in the index
+ * but may result in faster range search performance.  The
+ * default value, 16, was selected for a reasonable tradeoff
+ * of disk space consumption versus performance.  You can
+ * create a custom {@link LegacyFieldType} and invoke the {@link
+ * LegacyFieldType#setNumericPrecisionStep} method if you'd
+ * like to change the value.  Note that you must also
+ * specify a congruent value when creating {@link
+ * org.apache.lucene.legacy.LegacyNumericRangeQuery}.
+ * For low cardinality fields larger precision steps are good.
+ * If the cardinality is &lt; 100, it is fair
+ * to use {@link Integer#MAX_VALUE}, which produces one
+ * term per value.
+ *
+ * <p>For more information on the internals of numeric trie
+ * indexing, including the <a
+ * href="LegacyNumericRangeQuery.html#precisionStepDesc"><code>precisionStep</code></a>
+ * configuration, see {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}. The format of
+ * indexed values is described in {@link org.apache.lucene.legacy.LegacyNumericUtils}.
+ *
+ * <p>If you only need to sort by numeric value, and never
+ * run range querying/filtering, you can index using a
+ * <code>precisionStep</code> of {@link Integer#MAX_VALUE}.
+ * This will minimize disk space consumed.
+ *
+ * <p>More advanced users can instead use {@link
+ * org.apache.lucene.legacy.LegacyNumericTokenStream} directly, when indexing numbers. This
+ * class is a wrapper around this token stream type for
+ * easier, more intuitive usage.</p>
+ *
+ * @deprecated Please use {@link LongPoint} instead
+ *
+ * @since 2.9
+ */
+
+@Deprecated
+public final class LegacyLongField extends LegacyField {
+  
+  /** 
+   * Type for a LegacyLongField that is not stored:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_NOT_STORED = new LegacyFieldType();
+  static {
+    TYPE_NOT_STORED.setTokenized(true);
+    TYPE_NOT_STORED.setOmitNorms(true);
+    TYPE_NOT_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_NOT_STORED.setNumericType(LegacyNumericType.LONG);
+    TYPE_NOT_STORED.freeze();
+  }
+
+  /** 
+   * Type for a stored LegacyLongField:
+   * normalization factors, frequencies, and positions are omitted.
+   */
+  public static final LegacyFieldType TYPE_STORED = new LegacyFieldType();
+  static {
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS);
+    TYPE_STORED.setNumericType(LegacyNumericType.LONG);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.freeze();
+  }
+
+  /** Creates a stored or un-stored LegacyLongField with the provided value
+   *  and default <code>precisionStep</code> {@link
+   *  org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
+   *  @param name field name
+   *  @param value 64-bit long value
+   *  @param stored Store.YES if the content should also be stored
+   *  @throws IllegalArgumentException if the field name is null.
+   */
+  public LegacyLongField(String name, long value, Store stored) {
+    super(name, stored == Store.YES ? TYPE_STORED : TYPE_NOT_STORED);
+    fieldsData = Long.valueOf(value);
+  }
+  
+  /** Expert: allows you to customize the {@link
+   *  LegacyFieldType}. 
+   *  @param name field name
+   *  @param value 64-bit long value
+   *  @param type customized field type: must have {@link LegacyFieldType#numericType()}
+   *         of {@link LegacyNumericType#LONG}.
+   *  @throws IllegalArgumentException if the field name or type is null, or
+   *          if the field type does not have a LONG numericType()
+   */
+  public LegacyLongField(String name, long value, LegacyFieldType type) {
+    super(name, type);
+    if (type.numericType() != LegacyNumericType.LONG) {
+      throw new IllegalArgumentException("type.numericType() must be LONG but got " + type.numericType());
+    }
+    fieldsData = Long.valueOf(value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/105c7eae/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyNumericRangeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyNumericRangeQuery.java b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyNumericRangeQuery.java
new file mode 100644
index 0000000..f172a20
--- /dev/null
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/legacy/LegacyNumericRangeQuery.java
@@ -0,0 +1,537 @@
+/*
+ * 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.legacy;
+
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.Objects;
+
+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.FilteredTermsEnum;
+import org.apache.lucene.index.PointValues;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.util.AttributeSource;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.lucene.index.Term; // for javadocs
+
+/**
+ * <p>A {@link Query} that matches numeric values within a
+ * specified range.  To use this, you must first index the
+ * numeric values using {@link org.apache.lucene.legacy.LegacyIntField}, {@link
+ * org.apache.lucene.legacy.LegacyFloatField}, {@link org.apache.lucene.legacy.LegacyLongField} or {@link org.apache.lucene.legacy.LegacyDoubleField} (expert: {@link
+ * org.apache.lucene.legacy.LegacyNumericTokenStream}).  If your terms are instead textual,
+ * you should use {@link TermRangeQuery}.</p>
+ *
+ * <p>You create a new LegacyNumericRangeQuery with the static
+ * factory methods, eg:
+ *
+ * <pre class="prettyprint">
+ * Query q = LegacyNumericRangeQuery.newFloatRange("weight", 0.03f, 0.10f, true, true);
+ * </pre>
+ *
+ * matches all documents whose float valued "weight" field
+ * ranges from 0.03 to 0.10, inclusive.
+ *
+ * <p>The performance of LegacyNumericRangeQuery is much better
+ * than the corresponding {@link TermRangeQuery} because the
+ * number of terms that must be searched is usually far
+ * fewer, thanks to trie indexing, described below.</p>
+ *
+ * <p>You can optionally specify a <a
+ * href="#precisionStepDesc"><code>precisionStep</code></a>
+ * when creating this query.  This is necessary if you've
+ * changed this configuration from its default (4) during
+ * indexing.  Lower values consume more disk space but speed
+ * up searching.  Suitable values are between <b>1</b> and
+ * <b>8</b>. A good starting point to test is <b>4</b>,
+ * which is the default value for all <code>Numeric*</code>
+ * classes.  See <a href="#precisionStepDesc">below</a> for
+ * details.
+ *
+ * <p>This query defaults to {@linkplain
+ * MultiTermQuery#CONSTANT_SCORE_REWRITE}.
+ * With precision steps of &le;4, this query can be run with
+ * one of the BooleanQuery rewrite methods without changing
+ * BooleanQuery's default max clause count.
+ *
+ * <br><h3>How it works</h3>
+ *
+ * <p>See the publication about <a target="_blank" href="http://www.panfmp.org">panFMP</a>,
+ * where this algorithm was described (referred to as <code>TrieRangeQuery</code>):
+ *
+ * <blockquote><strong>Schindler, U, Diepenbroek, M</strong>, 2008.
+ * <em>Generic XML-based Framework for Metadata Portals.</em>
+ * Computers &amp; Geosciences 34 (12), 1947-1955.
+ * <a href="http://dx.doi.org/10.1016/j.cageo.2008.02.023"
+ * target="_blank">doi:10.1016/j.cageo.2008.02.023</a></blockquote>
+ *
+ * <p><em>A quote from this paper:</em> Because Apache Lucene is a full-text
+ * search engine and not a conventional database, it cannot handle numerical ranges
+ * (e.g., field value is inside user defined bounds, even dates are numerical values).
+ * We have developed an extension to Apache Lucene that stores
+ * the numerical values in a special string-encoded format with variable precision
+ * (all numerical values like doubles, longs, floats, and ints are converted to
+ * lexicographic sortable string representations and stored with different precisions
+ * (for a more detailed description of how the values are stored,
+ * see {@link org.apache.lucene.legacy.LegacyNumericUtils}). A range is then divided recursively into multiple intervals for searching:
+ * The center of the range is searched only with the lowest possible precision in the <em>trie</em>,
+ * while the boundaries are matched more exactly. This reduces the number of terms dramatically.</p>
+ *
+ * <p>For the variant that stores long values in 8 different precisions (each reduced by 8 bits) that
+ * uses a lowest precision of 1 byte, the index contains only a maximum of 256 distinct values in the
+ * lowest precision. Overall, a range could consist of a theoretical maximum of
+ * <code>7*255*2 + 255 = 3825</code> distinct terms (when there is a term for every distinct value of an
+ * 8-byte-number in the index and the range covers almost all of them; a maximum of 255 distinct values is used
+ * because it would always be possible to reduce the full 256 values to one term with degraded precision).
+ * In practice, we have seen up to 300 terms in most cases (index with 500,000 metadata records
+ * and a uniform value distribution).</p>
+ *
+ * <h3><a name="precisionStepDesc">Precision Step</a></h3>
+ * <p>You can choose any <code>precisionStep</code> when encoding values.
+ * Lower step values mean more precisions and so more terms in index (and index gets larger). The number
+ * of indexed terms per value is (those are generated by {@link org.apache.lucene.legacy.LegacyNumericTokenStream}):
+ * <p style="font-family:serif">
+ * &nbsp;&nbsp;indexedTermsPerValue = <b>ceil</b><big>(</big>bitsPerValue / precisionStep<big>)</big>
+ * </p>
+ * As the lower precision terms are shared by many values, the additional terms only
+ * slightly grow the term dictionary (approx. 7% for <code>precisionStep=4</code>), but have a larger
+ * impact on the postings (the postings file will have  more entries, as every document is linked to
+ * <code>indexedTermsPerValue</code> terms instead of one). The formula to estimate the growth
+ * of the term dictionary in comparison to one term per value:
+ * <p>
+ * <!-- the formula in the alt attribute was transformed from latex to PNG with http://1.618034.com/latex.php (with 110 dpi): -->
+ * &nbsp;&nbsp;<img src="doc-files/nrq-formula-1.png" alt="\mathrm{termDictOverhead} = \sum\limits_{i=0}^{\mathrm{indexedTermsPerValue}-1} \frac{1}{2^{\mathrm{precisionStep}\cdot i}}">
+ * </p>
+ * <p>On the other hand, if the <code>precisionStep</code> is smaller, the maximum number of terms to match reduces,
+ * which optimizes query speed. The formula to calculate the maximum number of terms that will be visited while
+ * executing the query is:
+ * <p>
+ * <!-- the formula in the alt attribute was transformed from latex to PNG with http://1.618034.com/latex.php (with 110 dpi): -->
+ * &nbsp;&nbsp;<img src="doc-files/nrq-formula-2.png" alt="\mathrm{maxQueryTerms} = \left[ \left( \mathrm{indexedTermsPerValue} - 1 \right) \cdot \left(2^\mathrm{precisionStep} - 1 \right) \cdot 2 \right] + \left( 2^\mathrm{precisionStep} - 1 \right)">
+ * </p>
+ * <p>For longs stored using a precision step of 4, <code>maxQueryTerms = 15*15*2 + 15 = 465</code>, and for a precision
+ * step of 2, <code>maxQueryTerms = 31*3*2 + 3 = 189</code>. But the faster search speed is reduced by more seeking
+ * in the term enum of the index. Because of this, the ideal <code>precisionStep</code> value can only
+ * be found out by testing. <b>Important:</b> You can index with a lower precision step value and test search speed
+ * using a multiple of the original step value.</p>
+ *
+ * <p>Good values for <code>precisionStep</code> are depending on usage and data type:
+ * <ul>
+ *  <li>The default for all data types is <b>4</b>, which is used, when no <code>precisionStep</code> is given.
+ *  <li>Ideal value in most cases for <em>64 bit</em> data types <em>(long, double)</em> is <b>6</b> or <b>8</b>.
+ *  <li>Ideal value in most cases for <em>32 bit</em> data types <em>(int, float)</em> is <b>4</b>.
+ *  <li>For low cardinality fields larger precision steps are good. If the cardinality is &lt; 100, it is
+ *  fair to use {@link Integer#MAX_VALUE} (see below).
+ *  <li>Steps <b>&ge;64</b> for <em>long/double</em> and <b>&ge;32</b> for <em>int/float</em> produces one token
+ *  per value in the index and querying is as slow as a conventional {@link TermRangeQuery}. But it can be used
+ *  to produce fields, that are solely used for sorting (in this case simply use {@link Integer#MAX_VALUE} as
+ *  <code>precisionStep</code>). Using {@link org.apache.lucene.legacy.LegacyIntField},
+ *  {@link org.apache.lucene.legacy.LegacyLongField}, {@link org.apache.lucene.legacy.LegacyFloatField} or {@link org.apache.lucene.legacy.LegacyDoubleField} for sorting
+ *  is ideal, because building the field cache is much faster than with text-only numbers.
+ *  These fields have one term per value and therefore also work with term enumeration for building distinct lists
+ *  (e.g. facets / preselected values to search for).
+ *  Sorting is also possible with range query optimized fields using one of the above <code>precisionSteps</code>.
+ * </ul>
+ *
+ * <p>Comparisons of the different types of RangeQueries on an index with about 500,000 docs showed
+ * that {@link TermRangeQuery} in boolean rewrite mode (with raised {@link BooleanQuery} clause count)
+ * took about 30-40 secs to complete, {@link TermRangeQuery} in constant score filter rewrite mode took 5 secs
+ * and executing this class took &lt;100ms to complete (on an Opteron64 machine, Java 1.5, 8 bit
+ * precision step). This query type was developed for a geographic portal, where the performance for
+ * e.g. bounding boxes or exact date/time stamps is important.</p>
+ *
+ * @deprecated Instead index with {@link IntPoint}, {@link LongPoint}, {@link FloatPoint}, {@link DoublePoint}, and
+ *             create range queries with {@link IntPoint#newRangeQuery(String, int, int) IntPoint.newRangeQuery()},
+ *             {@link LongPoint#newRangeQuery(String, long, long) LongPoint.newRangeQuery()},
+ *             {@link FloatPoint#newRangeQuery(String, float, float) FloatPoint.newRangeQuery()},
+ *             {@link DoublePoint#newRangeQuery(String, double, double) DoublePoint.newRangeQuery()} respectively.
+ *             See {@link PointValues} for background information on Points.
+ *
+ * @since 2.9
+ **/
+
+@Deprecated
+public final class LegacyNumericRangeQuery<T extends Number> extends MultiTermQuery {
+
+  private LegacyNumericRangeQuery(final String field, final int precisionStep, final LegacyNumericType dataType,
+                                  T min, T max, final boolean minInclusive, final boolean maxInclusive) {
+    super(field);
+    if (precisionStep < 1)
+      throw new IllegalArgumentException("precisionStep must be >=1");
+    this.precisionStep = precisionStep;
+    this.dataType = Objects.requireNonNull(dataType, "LegacyNumericType must not be null");
+    this.min = min;
+    this.max = max;
+    this.minInclusive = minInclusive;
+    this.maxInclusive = maxInclusive;
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>long</code>
+   * range using the given <a href="#precisionStepDesc"><code>precisionStep</code></a>.
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Long> newLongRange(final String field, final int precisionStep,
+    Long min, Long max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, precisionStep, LegacyNumericType.LONG, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>long</code>
+   * range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Long> newLongRange(final String field,
+    Long min, Long max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, LegacyNumericUtils.PRECISION_STEP_DEFAULT, LegacyNumericType.LONG, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>int</code>
+   * range using the given <a href="#precisionStepDesc"><code>precisionStep</code></a>.
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Integer> newIntRange(final String field, final int precisionStep,
+    Integer min, Integer max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, precisionStep, LegacyNumericType.INT, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>int</code>
+   * range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>. By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Integer> newIntRange(final String field,
+    Integer min, Integer max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, LegacyNumericUtils.PRECISION_STEP_DEFAULT_32, LegacyNumericType.INT, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>double</code>
+   * range using the given <a href="#precisionStepDesc"><code>precisionStep</code></a>.
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>.
+   * {@link Double#NaN} will never match a half-open range, to hit {@code NaN} use a query
+   * with {@code min == max == Double.NaN}.  By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Double> newDoubleRange(final String field, final int precisionStep,
+    Double min, Double max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, precisionStep, LegacyNumericType.DOUBLE, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>double</code>
+   * range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT} (16).
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>.
+   * {@link Double#NaN} will never match a half-open range, to hit {@code NaN} use a query
+   * with {@code min == max == Double.NaN}.  By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Double> newDoubleRange(final String field,
+    Double min, Double max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, LegacyNumericUtils.PRECISION_STEP_DEFAULT, LegacyNumericType.DOUBLE, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>float</code>
+   * range using the given <a href="#precisionStepDesc"><code>precisionStep</code></a>.
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>.
+   * {@link Float#NaN} will never match a half-open range, to hit {@code NaN} use a query
+   * with {@code min == max == Float.NaN}.  By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Float> newFloatRange(final String field, final int precisionStep,
+    Float min, Float max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, precisionStep, LegacyNumericType.FLOAT, min, max, minInclusive, maxInclusive);
+  }
+  
+  /**
+   * Factory that creates a <code>LegacyNumericRangeQuery</code>, that queries a <code>float</code>
+   * range using the default <code>precisionStep</code> {@link org.apache.lucene.legacy.LegacyNumericUtils#PRECISION_STEP_DEFAULT_32} (8).
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the min or max value to <code>null</code>.
+   * {@link Float#NaN} will never match a half-open range, to hit {@code NaN} use a query
+   * with {@code min == max == Float.NaN}.  By setting inclusive to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   */
+  public static LegacyNumericRangeQuery<Float> newFloatRange(final String field,
+    Float min, Float max, final boolean minInclusive, final boolean maxInclusive
+  ) {
+    return new LegacyNumericRangeQuery<>(field, LegacyNumericUtils.PRECISION_STEP_DEFAULT_32, LegacyNumericType.FLOAT, min, max, minInclusive, maxInclusive);
+  }
+
+  @Override @SuppressWarnings("unchecked")
+  protected TermsEnum getTermsEnum(final Terms terms, AttributeSource atts) throws IOException {
+    // very strange: java.lang.Number itself is not Comparable, but all subclasses used here are
+    if (min != null && max != null && ((Comparable<T>) min).compareTo(max) > 0) {
+      return TermsEnum.EMPTY;
+    }
+    return new NumericRangeTermsEnum(terms.iterator());
+  }
+
+  /** Returns <code>true</code> if the lower endpoint is inclusive */
+  public boolean includesMin() { return minInclusive; }
+  
+  /** Returns <code>true</code> if the upper endpoint is inclusive */
+  public boolean includesMax() { return maxInclusive; }
+
+  /** Returns the lower value of this range query */
+  public T getMin() { return min; }
+
+  /** Returns the upper value of this range query */
+  public T getMax() { return max; }
+  
+  /** Returns the precision step. */
+  public int getPrecisionStep() { return precisionStep; }
+  
+  @Override
+  public String toString(final String field) {
+    final StringBuilder sb = new StringBuilder();
+    if (!getField().equals(field)) sb.append(getField()).append(':');
+    return sb.append(minInclusive ? '[' : '{')
+      .append((min == null) ? "*" : min.toString())
+      .append(" TO ")
+      .append((max == null) ? "*" : max.toString())
+      .append(maxInclusive ? ']' : '}')
+      .toString();
+  }
+
+  @Override
+  @SuppressWarnings({"unchecked","rawtypes"})
+  public final boolean equals(final Object o) {
+    if (o==this) return true;
+    if (!super.equals(o))
+      return false;
+    if (o instanceof LegacyNumericRangeQuery) {
+      final LegacyNumericRangeQuery q=(LegacyNumericRangeQuery)o;
+      return (
+        (q.min == null ? min == null : q.min.equals(min)) &&
+        (q.max == null ? max == null : q.max.equals(max)) &&
+        minInclusive == q.minInclusive &&
+        maxInclusive == q.maxInclusive &&
+        precisionStep == q.precisionStep
+      );
+    }
+    return false;
+  }
+
+  @Override
+  public final int hashCode() {
+    int hash = super.hashCode();
+    hash = 31 * hash + precisionStep;
+    hash = 31 * hash + Objects.hashCode(min);
+    hash = 31 * hash + Objects.hashCode(max);
+    hash = 31 * hash + Objects.hashCode(minInclusive);
+    hash = 31 * hash + Objects.hashCode(maxInclusive);
+    return hash;
+  }
+
+  // members (package private, to be also fast accessible by NumericRangeTermEnum)
+  final int precisionStep;
+  final LegacyNumericType dataType;
+  final T min, max;
+  final boolean minInclusive,maxInclusive;
+
+  // used to handle float/double infinity correcty
+  static final long LONG_NEGATIVE_INFINITY =
+    NumericUtils.doubleToSortableLong(Double.NEGATIVE_INFINITY);
+  static final long LONG_POSITIVE_INFINITY =
+    NumericUtils.doubleToSortableLong(Double.POSITIVE_INFINITY);
+  static final int INT_NEGATIVE_INFINITY =
+    NumericUtils.floatToSortableInt(Float.NEGATIVE_INFINITY);
+  static final int INT_POSITIVE_INFINITY =
+    NumericUtils.floatToSortableInt(Float.POSITIVE_INFINITY);
+
+  /**
+   * Subclass of FilteredTermsEnum for enumerating all terms that match the
+   * sub-ranges for trie range queries, using flex API.
+   * <p>
+   * WARNING: This term enumeration is not guaranteed to be always ordered by
+   * {@link Term#compareTo}.
+   * The ordering depends on how {@link org.apache.lucene.legacy.LegacyNumericUtils#splitLongRange} and
+   * {@link org.apache.lucene.legacy.LegacyNumericUtils#splitIntRange} generates the sub-ranges. For
+   * {@link MultiTermQuery} ordering is not relevant.
+   */
+  private final class NumericRangeTermsEnum extends FilteredTermsEnum {
+
+    private BytesRef currentLowerBound, currentUpperBound;
+
+    private final LinkedList<BytesRef> rangeBounds = new LinkedList<>();
+
+    NumericRangeTermsEnum(final TermsEnum tenum) {
+      super(tenum);
+      switch (dataType) {
+        case LONG:
+        case DOUBLE: {
+          // lower
+          long minBound;
+          if (dataType == LegacyNumericType.LONG) {
+            minBound = (min == null) ? Long.MIN_VALUE : min.longValue();
+          } else {
+            assert dataType == LegacyNumericType.DOUBLE;
+            minBound = (min == null) ? LONG_NEGATIVE_INFINITY
+              : NumericUtils.doubleToSortableLong(min.doubleValue());
+          }
+          if (!minInclusive && min != null) {
+            if (minBound == Long.MAX_VALUE) break;
+            minBound++;
+          }
+          
+          // upper
+          long maxBound;
+          if (dataType == LegacyNumericType.LONG) {
+            maxBound = (max == null) ? Long.MAX_VALUE : max.longValue();
+          } else {
+            assert dataType == LegacyNumericType.DOUBLE;
+            maxBound = (max == null) ? LONG_POSITIVE_INFINITY
+              : NumericUtils.doubleToSortableLong(max.doubleValue());
+          }
+          if (!maxInclusive && max != null) {
+            if (maxBound == Long.MIN_VALUE) break;
+            maxBound--;
+          }
+          
+          LegacyNumericUtils.splitLongRange(new LegacyNumericUtils.LongRangeBuilder() {
+            @Override
+            public final void addRange(BytesRef minPrefixCoded, BytesRef maxPrefixCoded) {
+              rangeBounds.add(minPrefixCoded);
+              rangeBounds.add(maxPrefixCoded);
+            }
+          }, precisionStep, minBound, maxBound);
+          break;
+        }
+          
+        case INT:
+        case FLOAT: {
+          // lower
+          int minBound;
+          if (dataType == LegacyNumericType.INT) {
+            minBound = (min == null) ? Integer.MIN_VALUE : min.intValue();
+          } else {
+            assert dataType == LegacyNumericType.FLOAT;
+            minBound = (min == null) ? INT_NEGATIVE_INFINITY
+              : NumericUtils.floatToSortableInt(min.floatValue());
+          }
+          if (!minInclusive && min != null) {
+            if (minBound == Integer.MAX_VALUE) break;
+            minBound++;
+          }
+          
+          // upper
+          int maxBound;
+          if (dataType == LegacyNumericType.INT) {
+            maxBound = (max == null) ? Integer.MAX_VALUE : max.intValue();
+          } else {
+            assert dataType == LegacyNumericType.FLOAT;
+            maxBound = (max == null) ? INT_POSITIVE_INFINITY
+              : NumericUtils.floatToSortableInt(max.floatValue());
+          }
+          if (!maxInclusive && max != null) {
+            if (maxBound == Integer.MIN_VALUE) break;
+            maxBound--;
+          }
+          
+          LegacyNumericUtils.splitIntRange(new LegacyNumericUtils.IntRangeBuilder() {
+            @Override
+            public final void addRange(BytesRef minPrefixCoded, BytesRef maxPrefixCoded) {
+              rangeBounds.add(minPrefixCoded);
+              rangeBounds.add(maxPrefixCoded);
+            }
+          }, precisionStep, minBound, maxBound);
+          break;
+        }
+          
+        default:
+          // should never happen
+          throw new IllegalArgumentException("Invalid LegacyNumericType");
+      }
+    }
+    
+    private void nextRange() {
+      assert rangeBounds.size() % 2 == 0;
+
+      currentLowerBound = rangeBounds.removeFirst();
+      assert currentUpperBound == null || currentUpperBound.compareTo(currentLowerBound) <= 0 :
+        "The current upper bound must be <= the new lower bound";
+      
+      currentUpperBound = rangeBounds.removeFirst();
+    }
+    
+    @Override
+    protected final BytesRef nextSeekTerm(BytesRef term) {
+      while (rangeBounds.size() >= 2) {
+        nextRange();
+        
+        // if the new upper bound is before the term parameter, the sub-range is never a hit
+        if (term != null && term.compareTo(currentUpperBound) > 0)
+          continue;
+        // never seek backwards, so use current term if lower bound is smaller
+        return (term != null && term.compareTo(currentLowerBound) > 0) ?
+          term : currentLowerBound;
+      }
+      
+      // no more sub-range enums available
+      assert rangeBounds.isEmpty();
+      currentLowerBound = currentUpperBound = null;
+      return null;
+    }
+    
+    @Override
+    protected final AcceptStatus accept(BytesRef term) {
+      while (currentUpperBound == null || term.compareTo(currentUpperBound) > 0) {
+        if (rangeBounds.isEmpty())
+          return AcceptStatus.END;
+        // peek next sub-range, only seek if the current term is smaller than next lower bound
+        if (term.compareTo(rangeBounds.getFirst()) < 0)
+          return AcceptStatus.NO_AND_SEEK;
+        // step forward to next range without seeking, as next lower range bound is less or equal current term
+        nextRange();
+      }
+      return AcceptStatus.YES;
+    }
+
+  }
+  
+}