This is an automated email from the ASF dual-hosted git repository.
markrmiller pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 797bb38 SOLR-15538 Update Lucene Preview Release dependency.
797bb38 is described below
commit 797bb38c50fed9e533ca20de920c63c6c35256a9
Author: Mark Robert Miller <[email protected]>
AuthorDate: Thu Jul 29 12:05:55 2021 -0500
SOLR-15538 Update Lucene Preview Release dependency.
---
gradle/globals.gradle | 2 +-
.../apache/solr/schema/TestICUCollationField.java | 2 +-
.../org/apache/solr/analysis/TokenizerChain.java | 1 -
.../solr/highlight/DefaultSolrHighlighter.java | 3 +
.../solr/index/SlowCompositeReaderWrapper.java | 8 +-
.../apache/solr/parser/SolrQueryParserBase.java | 2 +-
.../src/java/org/apache/solr/schema/FieldType.java | 4 -
.../apache/solr/schema/FieldTypePluginLoader.java | 1 -
.../java/org/apache/solr/schema/SchemaField.java | 6 +-
.../apache/solr/search/ExtendedDismaxQParser.java | 2 +-
.../solr/search/PayloadCheckQParserPlugin.java | 2 +-
.../solr/search/PayloadScoreQParserPlugin.java | 2 +-
.../search/similarities/BM25SimilarityFactory.java | 1 +
.../similarities/SchemaSimilarityFactory.java | 46 +-
.../spelling/suggest/jaspell/JaspellLookup.java | 208 ++++++
.../suggest/jaspell/JaspellLookupFactory.java | 1 -
.../suggest/jaspell/JaspellTernarySearchTrie.java | 831 +++++++++++++++++++++
.../spelling/suggest/jaspell/package-info.java | 2 +-
.../java/org/apache/solr/util/PayloadUtils.java | 9 +-
.../solr/collection1/conf/schema-bm25.xml | 1 +
.../conf/solrconfig-tieredmergepolicyfactory.xml | 2 +-
.../solr/analysis/TestLuceneMatchVersion.java | 1 -
.../TestReversedWildcardFilterFactory.java | 2 +-
.../apache/solr/core/TestMergePolicyConfig.java | 1 -
.../solr/handler/TestSnapshotCoreBackup.java | 2 +-
.../solr/handler/TestStressThreadBackup.java | 2 +-
.../org/apache/solr/highlight/HighlighterTest.java | 2 +-
.../apache/solr/rest/schema/TestBulkSchemaAPI.java | 3 +-
.../search/ApacheLuceneSolrNearQueryBuilder.java | 6 +-
.../solr/search/ChooseOneWordQueryBuilder.java | 4 +-
.../org/apache/solr/search/FuzzySearchTest.java | 67 --
.../org/apache/solr/search/HandyQueryBuilder.java | 4 +-
.../test/org/apache/solr/search/TestDocSet.java | 13 +-
.../org/apache/solr/search/TestSolrCoreParser.java | 22 +-
.../apache/solr/update/SolrIndexConfigTest.java | 3 +-
.../solr/client/solrj/request/SchemaTest.java | 2 -
versions.lock | 54 +-
versions.props | 2 +-
38 files changed, 1144 insertions(+), 182 deletions(-)
diff --git a/gradle/globals.gradle b/gradle/globals.gradle
index 816d77b..bf84fca 100644
--- a/gradle/globals.gradle
+++ b/gradle/globals.gradle
@@ -20,7 +20,7 @@ allprojects {
group "org.apache"
- def lucenePrereleaseBuild = '5'
+ def lucenePrereleaseBuild = '9'
// Repositories to fetch dependencies from.
repositories {
diff --git
a/solr/contrib/analysis-extras/src/test/org/apache/solr/schema/TestICUCollationField.java
b/solr/contrib/analysis-extras/src/test/org/apache/solr/schema/TestICUCollationField.java
index 844abad..6c4ecb5 100644
---
a/solr/contrib/analysis-extras/src/test/org/apache/solr/schema/TestICUCollationField.java
+++
b/solr/contrib/analysis-extras/src/test/org/apache/solr/schema/TestICUCollationField.java
@@ -98,7 +98,7 @@ public class TestICUCollationField extends SolrTestCaseJ4 {
Mockito.when(loader.openResource(Mockito.anyString()))
.thenReturn(new
ByteArrayInputStream(tailoredRules.getBytes(StandardCharsets.UTF_8)));
} else {
- loader = new FilesystemResourceLoader(confDir.toPath());
+ loader = new FilesystemResourceLoader(confDir.toPath(),
TestICUCollationField.class.getClassLoader());
}
final Collator readCollator =
ICUCollationField.createFromRules(osFileName, loader);
assertEquals(tailoredCollator, readCollator);
diff --git a/solr/core/src/java/org/apache/solr/analysis/TokenizerChain.java
b/solr/core/src/java/org/apache/solr/analysis/TokenizerChain.java
index 9533f3d..611e3cf 100644
--- a/solr/core/src/java/org/apache/solr/analysis/TokenizerChain.java
+++ b/solr/core/src/java/org/apache/solr/analysis/TokenizerChain.java
@@ -49,7 +49,6 @@ public final class TokenizerChain extends SolrAnalyzer {
customAnalyzer.getTokenizerFactory(),
customAnalyzer.getTokenFilterFactories().toArray(new
TokenFilterFactory[0]));
setPositionIncrementGap(customAnalyzer.getPositionIncrementGap(null));
- setVersion(customAnalyzer.getVersion());
assert customAnalyzer.getOffsetGap(null) == 1; // note: we don't support
setting the offset gap
}
diff --git
a/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
b/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
index dba39e6..a92005f 100644
--- a/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
+++ b/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
@@ -972,12 +972,14 @@ public class DefaultSolrHighlighter extends
SolrHighlighter implements PluginInf
}
}
+
/**
* Wraps a DirectoryReader that caches the {@link
LeafReader#getTermVectors(int)} so that
* if the next call has the same ID, then it is reused.
*/
static class TermVectorReusingLeafReader extends FilterLeafReader {
+
private int lastDocId = -1;
private Fields tvFields;
@@ -994,6 +996,7 @@ public class DefaultSolrHighlighter extends SolrHighlighter
implements PluginInf
return tvFields;
}
+
@Override
public CacheHelper getCoreCacheHelper() {
return null;
diff --git
a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
index 14b4c0f..981f5a9 100644
--- a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
+++ b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
@@ -241,10 +241,9 @@ public final class SlowCompositeReaderWrapper extends
LeafReader {
ensureOpen();
return MultiDocValues.getNormValues(in, field); // TODO cache?
}
-
+
@Override
public Fields getTermVectors(int docID) throws IOException {
- ensureOpen();
return in.getTermVectors(docID);
}
@@ -281,13 +280,12 @@ public final class SlowCompositeReaderWrapper extends
LeafReader {
@Override
public VectorValues getVectorValues(String field) {
ensureOpen();
- return null; // because not supported. Throw UOE?
+ return VectorValues.EMPTY;
}
@Override
- public TopDocs searchNearestVectors(String field, float[] target, int k, int
fanout)
+ public TopDocs searchNearestVectors(String field, float[] target, int k,
Bits acceptDocs)
throws IOException {
- ensureOpen();
return null; // because not supported. Throw UOE?
}
diff --git a/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java
b/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java
index fc12c6b..54b0574 100644
--- a/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java
+++ b/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java
@@ -1254,7 +1254,7 @@ public abstract class SolrQueryParserBase extends
QueryBuilder {
Automata.makeChar(factory.getMarkerChar()),
Automata.makeAnyString());
// subtract these away
- automaton = Operations.minus(automaton, falsePositives,
Operations.DEFAULT_MAX_DETERMINIZED_STATES);
+ automaton = Operations.minus(automaton, falsePositives,
Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
}
return new AutomatonQuery(term, automaton) {
// override toString so it's completely transparent
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java
b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index f3e995c..0a7a47a 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -64,7 +64,6 @@ import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.apache.lucene.util.CharsRef;
import org.apache.lucene.util.CharsRefBuilder;
-import org.apache.lucene.util.Version;
import org.apache.solr.analysis.SolrAnalyzer;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.IteratorWriter;
@@ -1264,9 +1263,6 @@ public abstract class FieldType extends FieldProperties {
}
} else { // analyzer is not instanceof TokenizerChain
analyzerProps.add(CLASS_NAME, analyzer.getClass().getName());
- if (analyzer.getVersion() != Version.LATEST) {
- analyzerProps.add(LUCENE_MATCH_VERSION_PARAM,
analyzer.getVersion().toString());
- }
}
return analyzerProps;
}
diff --git
a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
index 2e35dc5..8693e76 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
@@ -221,7 +221,6 @@ public final class FieldTypePluginLoader
"Configuration Error: Analyzer '" + clazz.getName() +
"' needs a '" + IndexSchema.LUCENE_MATCH_VERSION_PARAM + "'
parameter");
}
- analyzer.setVersion(luceneMatchVersion);
return analyzer;
} catch (Exception e) {
log.error("Cannot load analyzer: {}", analyzerName, e);
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaField.java
b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
index 3d7740e..ebb3c0c 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
@@ -26,7 +26,7 @@ import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.IndexableFieldType;
-import org.apache.lucene.index.VectorValues;
+import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.search.SortField;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.SimpleOrderedMap;
@@ -454,8 +454,8 @@ public final class SchemaField extends FieldProperties
implements IndexableField
}
@Override
- public VectorValues.SimilarityFunction vectorSimilarityFunction() {
- return VectorValues.SimilarityFunction.NONE;
+ public VectorSimilarityFunction vectorSimilarityFunction() {
+ return VectorSimilarityFunction.EUCLIDEAN;
}
@Override
diff --git
a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
index 42fa504..1663c93 100644
--- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
@@ -40,6 +40,7 @@ import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.ProductFloatFunction;
import org.apache.lucene.queries.function.valuesource.QueryValueSource;
+import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -48,7 +49,6 @@ import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanQuery;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
diff --git
a/solr/core/src/java/org/apache/solr/search/PayloadCheckQParserPlugin.java
b/solr/core/src/java/org/apache/solr/search/PayloadCheckQParserPlugin.java
index a4a3db5..811fe6b 100644
--- a/solr/core/src/java/org/apache/solr/search/PayloadCheckQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/PayloadCheckQParserPlugin.java
@@ -31,8 +31,8 @@ import org.apache.lucene.analysis.payloads.PayloadEncoder;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery.MatchOperation;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery.PayloadType;
+import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
diff --git
a/solr/core/src/java/org/apache/solr/search/PayloadScoreQParserPlugin.java
b/solr/core/src/java/org/apache/solr/search/PayloadScoreQParserPlugin.java
index 45f39c7..a2797a2 100644
--- a/solr/core/src/java/org/apache/solr/search/PayloadScoreQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/PayloadScoreQParserPlugin.java
@@ -23,8 +23,8 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queries.payloads.PayloadDecoder;
import org.apache.lucene.queries.payloads.PayloadFunction;
import org.apache.lucene.queries.payloads.PayloadScoreQuery;
+import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanQuery;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
diff --git
a/solr/core/src/java/org/apache/solr/search/similarities/BM25SimilarityFactory.java
b/solr/core/src/java/org/apache/solr/search/similarities/BM25SimilarityFactory.java
index 2a01d28..8c1661e 100644
---
a/solr/core/src/java/org/apache/solr/search/similarities/BM25SimilarityFactory.java
+++
b/solr/core/src/java/org/apache/solr/search/similarities/BM25SimilarityFactory.java
@@ -23,6 +23,7 @@ import org.apache.solr.schema.SimilarityFactory;
/**
* Factory for BM25Similarity. This is the default similarity since 8.x.
+ *
* <p>
* Parameters:
* <ul>
diff --git
a/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java
b/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java
index d08e918..9609e0f 100644
---
a/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java
+++
b/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java
@@ -31,11 +31,15 @@ import org.apache.solr.util.plugin.SolrCoreAware;
* <p>
* <code>SimilarityFactory</code> that returns a global {@link
PerFieldSimilarityWrapper}
* that delegates to the field type, if it's configured. For field types that
- * do not have a <code>Similarity</code> explicitly configured, the global
<code>Similarity</code>
- * will use per fieldtype defaults -- either based on an explicitly configured
- * <code>defaultSimFromFieldType</code> or {@link BM25Similarity} as a
sensible default.
+ * do not have a <code>Similarity</code> explicitly configured, the global
<code>Similarity</code>
+ * will use per fieldtype defaults -- either based on an explicitly configured
+ * <code>defaultSimFromFieldType</code> a sensible default:
+ * </p>
+ * <ul>
+ * <li><code>luceneMatchVersion >= 8.0</code> = {@link BM25Similarity}</li>
+ * </ul>
* <p>
- * The <code>defaultSimFromFieldType</code> option accepts the name of any
fieldtype, and uses
+ * The <code>defaultSimFromFieldType</code> option accepts the name of any
fieldtype, and uses
* whatever <code>Similarity</code> is explicitly configured for that
fieldType as the default for
* all other field types. For example:
* </p>
@@ -55,15 +59,15 @@ import org.apache.solr.util.plugin.SolrCoreAware;
* </fieldType>
* </pre>
* <p>
- * In the example above, any fieldtypes that do not define their own
<code></similarity/></code>
+ * In the example above, any fieldtypes that do not define their own
<code></similarity/></code>
* will use the <code>Similarity</code> configured for the
<code>type-using-custom-dfr</code>.
* </p>
- *
+ *
* <p>
- * <b>NOTE:</b> Users should be aware that even when this factory uses a
single default
- * <code>Similarity</code> for some or all fields in a Query, the behavior can
be inconsistent
- * with the behavior of explicitly configuring that same
<code>Similarity</code> globally, because
- * of differences in how some multi-field / multi-clause behavior is defined
in
+ * <b>NOTE:</b> Users should be aware that even when this factory uses a
single default
+ * <code>Similarity</code> for some or all fields in a Query, the behavior can
be inconsistent
+ * with the behavior of explicitly configuring that same
<code>Similarity</code> globally, because
+ * of differences in how some multi-field / multi-clause behavior is defined in
* <code>PerFieldSimilarityWrapper</code>.
* </p>
*
@@ -72,9 +76,9 @@ import org.apache.solr.util.plugin.SolrCoreAware;
public class SchemaSimilarityFactory extends SimilarityFactory implements
SolrCoreAware {
private static final String INIT_OPT = "defaultSimFromFieldType";
-
+
private String defaultSimFromFieldType; // set by init, if null use sensible
implicit default
-
+
private volatile SolrCore core; // set by inform(SolrCore)
private volatile Similarity similarity; // lazy instantiated
@@ -82,7 +86,7 @@ public class SchemaSimilarityFactory extends
SimilarityFactory implements SolrCo
public void inform(SolrCore core) {
this.core = core;
}
-
+
@Override
public void init(SolrParams args) {
defaultSimFromFieldType = args.get(INIT_OPT, null);
@@ -97,7 +101,7 @@ public class SchemaSimilarityFactory extends
SimilarityFactory implements SolrCo
if (null == similarity) {
// Need to instantiate lazily, can't do this in inform(SolrCore) because
of chicken/egg
// circular initialization hell with core.getLatestSchema() to lookup
defaultSimFromFieldType
-
+
Similarity defaultSim = null;
if (null == defaultSimFromFieldType) {
// nothing configured, choose a sensible implicit default...
@@ -106,23 +110,23 @@ public class SchemaSimilarityFactory extends
SimilarityFactory implements SolrCo
FieldType defSimFT =
core.getLatestSchema().getFieldTypeByName(defaultSimFromFieldType);
if (null == defSimFT) {
throw new SolrException(ErrorCode.SERVER_ERROR,
- "SchemaSimilarityFactory configured with " +
INIT_OPT + "='" +
- defaultSimFromFieldType + "' but that
<fieldType> does not exist");
-
+ "SchemaSimilarityFactory configured with " + INIT_OPT + "='" +
+ defaultSimFromFieldType + "' but that <fieldType> does not
exist");
+
}
defaultSim = defSimFT.getSimilarity();
if (null == defaultSim) {
throw new SolrException(ErrorCode.SERVER_ERROR,
- "SchemaSimilarityFactory configured with " +
INIT_OPT + "='" +
- defaultSimFromFieldType +
- "' but that <fieldType> does not define a
<similarity>");
+ "SchemaSimilarityFactory configured with " + INIT_OPT + "='" +
+ defaultSimFromFieldType +
+ "' but that <fieldType> does not define a <similarity>");
}
}
similarity = new SchemaSimilarity(defaultSim);
}
return similarity;
}
-
+
private class SchemaSimilarity extends PerFieldSimilarityWrapper {
private Similarity defaultSimilarity;
diff --git
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookup.java
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookup.java
new file mode 100644
index 0000000..ecbb7f6
--- /dev/null
+++
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookup.java
@@ -0,0 +1,208 @@
+/*
+ * 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.solr.spelling.suggest.jaspell;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.apache.lucene.search.suggest.InputIterator;
+import org.apache.lucene.search.suggest.Lookup;
+import org.apache.lucene.store.DataInput;
+import org.apache.lucene.store.DataOutput;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.CharsRef;
+import org.apache.lucene.util.CharsRefBuilder;
+import
org.apache.solr.spelling.suggest.jaspell.JaspellTernarySearchTrie.TSTNode;
+
+/**
+ * Suggest implementation based on <a
href="http://jaspell.sourceforge.net/">JaSpell</a>.
+ *
+ * @see JaspellTernarySearchTrie
+ * @deprecated Migrate to one of the newer suggesters which are much more RAM
efficient.
+ */
+@Deprecated
+public class JaspellLookup extends Lookup {
+ JaspellTernarySearchTrie trie = new JaspellTernarySearchTrie();
+ private boolean usePrefix = true;
+ private int editDistance = 2;
+
+ /** Number of entries the lookup was built with */
+ private long count = 0;
+
+ /**
+ * Creates a new empty trie
+ *
+ * @see #build(InputIterator)
+ */
+ public JaspellLookup() {}
+
+ @Override
+ public void build(InputIterator iterator) throws IOException {
+ if (iterator.hasPayloads()) {
+ throw new IllegalArgumentException("this suggester doesn't support
payloads");
+ }
+ if (iterator.hasContexts()) {
+ throw new IllegalArgumentException("this suggester doesn't support
contexts");
+ }
+ count = 0;
+ trie = new JaspellTernarySearchTrie();
+ trie.setMatchAlmostDiff(editDistance);
+ BytesRef spare;
+ final CharsRefBuilder charsSpare = new CharsRefBuilder();
+
+ while ((spare = iterator.next()) != null) {
+ final long weight = iterator.weight();
+ if (spare.length == 0) {
+ continue;
+ }
+ charsSpare.copyUTF8Bytes(spare);
+ trie.put(charsSpare.toString(), weight);
+ count++;
+ }
+ }
+
+ /**
+ * Adds a new node if <code>key</code> already exists, otherwise replaces
its value.
+ *
+ * <p>This method always returns false.
+ */
+ public boolean add(CharSequence key, Object value) {
+ trie.put(key, value);
+ // XXX
+ return false;
+ }
+
+ /** Returns the value for the specified key, or null if the key does not
exist. */
+ public Object get(CharSequence key) {
+ return trie.get(key);
+ }
+
+ @Override
+ public List<LookupResult> lookup(
+ CharSequence key, Set<BytesRef> contexts, boolean onlyMorePopular, int
num) {
+ if (contexts != null) {
+ throw new IllegalArgumentException("this suggester doesn't support
contexts");
+ }
+ List<LookupResult> res = new ArrayList<>();
+ List<String> list;
+ int count = onlyMorePopular ? num * 2 : num;
+ if (usePrefix) {
+ list = trie.matchPrefix(key, count);
+ } else {
+ list = trie.matchAlmost(key, count);
+ }
+ if (list == null || list.size() == 0) {
+ return res;
+ }
+ int maxCnt = Math.min(num, list.size());
+ if (onlyMorePopular) {
+ LookupPriorityQueue queue = new LookupPriorityQueue(num);
+ for (String s : list) {
+ long freq = ((Number) trie.get(s)).longValue();
+ queue.insertWithOverflow(new LookupResult(new CharsRef(s), freq));
+ }
+ for (LookupResult lr : queue.getResults()) {
+ res.add(lr);
+ }
+ } else {
+ for (int i = 0; i < maxCnt; i++) {
+ String s = list.get(i);
+ long freq = ((Number) trie.get(s)).longValue();
+ res.add(new LookupResult(new CharsRef(s), freq));
+ }
+ }
+ return res;
+ }
+
+ private static final byte LO_KID = 0x01;
+ private static final byte EQ_KID = 0x02;
+ private static final byte HI_KID = 0x04;
+ private static final byte HAS_VALUE = 0x08;
+
+ private void readRecursively(DataInput in, TSTNode node) throws IOException {
+ node.splitchar = in.readString().charAt(0);
+ byte mask = in.readByte();
+ if ((mask & HAS_VALUE) != 0) {
+ node.data = in.readLong();
+ }
+ if ((mask & LO_KID) != 0) {
+ TSTNode kid = new TSTNode('\0', node);
+ node.relatives[TSTNode.LOKID] = kid;
+ readRecursively(in, kid);
+ }
+ if ((mask & EQ_KID) != 0) {
+ TSTNode kid = new TSTNode('\0', node);
+ node.relatives[TSTNode.EQKID] = kid;
+ readRecursively(in, kid);
+ }
+ if ((mask & HI_KID) != 0) {
+ TSTNode kid = new TSTNode('\0', node);
+ node.relatives[TSTNode.HIKID] = kid;
+ readRecursively(in, kid);
+ }
+ }
+
+ private void writeRecursively(DataOutput out, TSTNode node) throws
IOException {
+ if (node == null) {
+ return;
+ }
+ out.writeString(new String(new char[] {node.splitchar}, 0, 1));
+ byte mask = 0;
+ if (node.relatives[TSTNode.LOKID] != null) mask |= LO_KID;
+ if (node.relatives[TSTNode.EQKID] != null) mask |= EQ_KID;
+ if (node.relatives[TSTNode.HIKID] != null) mask |= HI_KID;
+ if (node.data != null) mask |= HAS_VALUE;
+ out.writeByte(mask);
+ if (node.data != null) {
+ out.writeLong(((Number) node.data).longValue());
+ }
+ writeRecursively(out, node.relatives[TSTNode.LOKID]);
+ writeRecursively(out, node.relatives[TSTNode.EQKID]);
+ writeRecursively(out, node.relatives[TSTNode.HIKID]);
+ }
+
+ @Override
+ public boolean store(DataOutput output) throws IOException {
+ output.writeVLong(count);
+ TSTNode root = trie.getRoot();
+ if (root == null) { // empty tree
+ return false;
+ }
+ writeRecursively(output, root);
+ return true;
+ }
+
+ @Override
+ public boolean load(DataInput input) throws IOException {
+ count = input.readVLong();
+ TSTNode root = new TSTNode('\0', null);
+ readRecursively(input, root);
+ trie.setRoot(root);
+ return true;
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ return trie.ramBytesUsed();
+ }
+
+ @Override
+ public long getCount() {
+ return count;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookupFactory.java
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookupFactory.java
index f64bc98..07c9978 100644
---
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookupFactory.java
+++
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellLookupFactory.java
@@ -19,7 +19,6 @@ package org.apache.solr.spelling.suggest.jaspell;
import java.lang.invoke.MethodHandles;
import org.apache.lucene.search.suggest.Lookup;
-import org.apache.lucene.search.suggest.jaspell.JaspellLookup;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.spelling.suggest.LookupFactory;
diff --git
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellTernarySearchTrie.java
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellTernarySearchTrie.java
new file mode 100644
index 0000000..4aad9c3
--- /dev/null
+++
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/JaspellTernarySearchTrie.java
@@ -0,0 +1,831 @@
+/*
+ * Copyright (c) 2005 Bruno Martins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the organization nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.solr.spelling.suggest.jaspell;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.zip.GZIPInputStream;
+import org.apache.lucene.util.Accountable;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.RamUsageEstimator;
+
+/**
+ * Implementation of a Ternary Search Trie, a data structure for storing
<code>String</code> objects
+ * that combines the compact size of a binary search tree with the speed of a
digital search trie,
+ * and is therefore ideal for practical use in sorting and searching data.
+ *
+ * <p>This data structure is faster than hashing for many typical search
problems, and supports a
+ * broader range of useful problems and operations. Ternary searches are
faster than hashing and
+ * more powerful, too.
+ *
+ * <p>The theory of ternary search trees was described at a symposium in 1997
(see "Fast Algorithms
+ * for Sorting and Searching Strings," by J.L. Bentley and R. Sedgewick,
Proceedings of the 8th
+ * Annual ACM-SIAM Symposium on Discrete Algorithms, January 1997). Algorithms
in C, Third Edition,
+ * by Robert Sedgewick (Addison-Wesley, 1998) provides yet another view of
ternary search trees.
+ *
+ * @deprecated Migrate to one of the newer suggesters which are much more RAM
efficient.
+ */
+@Deprecated
+public class JaspellTernarySearchTrie implements Accountable {
+
+ /** An inner class of Ternary Search Trie that represents a node in the
trie. */
+ protected static final class TSTNode implements Accountable {
+
+ /** Index values for accessing relatives array. */
+ protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3;
+
+ /** The key to the node. */
+ protected Object data;
+
+ /** The relative nodes. */
+ protected final TSTNode[] relatives = new TSTNode[4];
+
+ /** The char used in the split. */
+ protected char splitchar;
+
+ /**
+ * Constructor method.
+ *
+ * @param splitchar The char used in the split.
+ * @param parent The parent node.
+ */
+ protected TSTNode(char splitchar, TSTNode parent) {
+ this.splitchar = splitchar;
+ relatives[PARENT] = parent;
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long mem = RamUsageEstimator.shallowSizeOf(this) +
RamUsageEstimator.shallowSizeOf(relatives);
+ // We don't need to add parent since our parent added itself:
+ for (int i = 1; i < 4; i++) {
+ TSTNode node = relatives[i];
+ if (node != null) {
+ mem += node.ramBytesUsed();
+ }
+ }
+ return mem;
+ }
+ }
+
+ /**
+ * Compares characters by alphabetical order.
+ *
+ * @param cCompare2 The first char in the comparison.
+ * @param cRef The second char in the comparison.
+ * @return A negative number, 0 or a positive number if the second char is
less, equal or greater.
+ */
+ private static int compareCharsAlphabetically(char cCompare2, char cRef) {
+ return Character.toLowerCase(cCompare2) - Character.toLowerCase(cRef);
+ }
+
+ /* what follows is the original Jaspell code.
+ private static int compareCharsAlphabetically(int cCompare2, int cRef) {
+ int cCompare = 0;
+ if (cCompare2 >= 65) {
+ if (cCompare2 < 89) {
+ cCompare = (2 * cCompare2) - 65;
+ } else if (cCompare2 < 97) {
+ cCompare = cCompare2 + 24;
+ } else if (cCompare2 < 121) {
+ cCompare = (2 * cCompare2) - 128;
+ } else cCompare = cCompare2;
+ } else cCompare = cCompare2;
+ if (cRef < 65) {
+ return cCompare - cRef;
+ }
+ if (cRef < 89) {
+ return cCompare - ((2 * cRef) - 65);
+ }
+ if (cRef < 97) {
+ return cCompare - (cRef + 24);
+ }
+ if (cRef < 121) {
+ return cCompare - ((2 * cRef) - 128);
+ }
+ return cCompare - cRef;
+ }
+ */
+
+ /** The default number of values returned by the <code>matchAlmost</code>
method. */
+ private int defaultNumReturnValues = -1;
+
+ /** the number of differences allowed in a call to the
<code>matchAlmostKey</code> method. */
+ private int matchAlmostDiff;
+
+ /** The base node in the trie. */
+ private TSTNode rootNode;
+
+ private final Locale locale;
+
+ /** Constructs an empty Ternary Search Trie. */
+ public JaspellTernarySearchTrie() {
+ this(Locale.ROOT);
+ }
+
+ /** Constructs an empty Ternary Search Trie, specifying the Locale used for
lowercasing. */
+ public JaspellTernarySearchTrie(Locale locale) {
+ this.locale = locale;
+ }
+
+ // for loading
+ void setRoot(TSTNode newRoot) {
+ rootNode = newRoot;
+ }
+
+ // for saving
+ TSTNode getRoot() {
+ return rootNode;
+ }
+
+ /**
+ * Constructs a Ternary Search Trie and loads data from a <code>Path</code>
into the Trie. The
+ * file is a normal text document, where each line is of the form word TAB
float.
+ *
+ * @param file The <code>Path</code> with the data to load into the Trie.
+ * @exception IOException A problem occurred while reading the data.
+ */
+ public JaspellTernarySearchTrie(Path file) throws IOException {
+ this(file, false);
+ }
+
+ /**
+ * Constructs a Ternary Search Trie and loads data from a <code>File</code>
into the Trie. The
+ * file is a normal text document, where each line is of the form "word TAB
float".
+ *
+ * @param file The <code>File</code> with the data to load into the Trie.
+ * @param compression If true, the file is compressed with the GZIP
algorithm, and if false, the
+ * file is a normal text document.
+ * @exception IOException A problem occurred while reading the data.
+ */
+ public JaspellTernarySearchTrie(Path file, boolean compression) throws
IOException {
+ this();
+ BufferedReader in;
+ if (compression)
+ in =
+ new BufferedReader(
+ IOUtils.getDecodingReader(
+ new GZIPInputStream(Files.newInputStream(file)),
StandardCharsets.UTF_8));
+ else in = Files.newBufferedReader(file, StandardCharsets.UTF_8);
+ try {
+ String word;
+ int pos;
+ Float occur, one = 1f;
+ while ((word = in.readLine()) != null) {
+ pos = word.indexOf("\t");
+ occur = one;
+ if (pos != -1) {
+ occur = Float.parseFloat(word.substring(pos + 1).trim());
+ word = word.substring(0, pos);
+ }
+ String key = word.toLowerCase(locale);
+ if (rootNode == null) {
+ rootNode = new TSTNode(key.charAt(0), null);
+ }
+ TSTNode node = null;
+ if (key.length() > 0 && rootNode != null) {
+ TSTNode currentNode = rootNode;
+ int charIndex = 0;
+ while (true) {
+ if (currentNode == null) break;
+ int charComp = compareCharsAlphabetically(key.charAt(charIndex),
currentNode.splitchar);
+ if (charComp == 0) {
+ charIndex++;
+ if (charIndex == key.length()) {
+ node = currentNode;
+ break;
+ }
+ currentNode = currentNode.relatives[TSTNode.EQKID];
+ } else if (charComp < 0) {
+ currentNode = currentNode.relatives[TSTNode.LOKID];
+ } else {
+ currentNode = currentNode.relatives[TSTNode.HIKID];
+ }
+ }
+ Float occur2 = null;
+ if (node != null) occur2 = ((Float) (node.data));
+ if (occur2 != null) {
+ occur += occur2.floatValue();
+ }
+ currentNode = getOrCreateNode(word.trim().toLowerCase(locale));
+ currentNode.data = occur;
+ }
+ }
+ } finally {
+ IOUtils.close(in);
+ }
+ }
+
+ /**
+ * Deletes the node passed in as an argument. If this node has non-null
data, then both the node
+ * and the data will be deleted. It also deletes any other nodes in the trie
that are no longer
+ * needed after the deletion of the node.
+ *
+ * @param nodeToDelete The node to delete.
+ */
+ private void deleteNode(TSTNode nodeToDelete) {
+ if (nodeToDelete == null) {
+ return;
+ }
+ nodeToDelete.data = null;
+ while (nodeToDelete != null) {
+ nodeToDelete = deleteNodeRecursion(nodeToDelete);
+ // deleteNodeRecursion(nodeToDelete);
+ }
+ }
+
+ /**
+ * Recursively visits each node to be deleted.
+ *
+ * <p>To delete a node, first set its data to null, then pass it into this
method, then pass the
+ * node returned by this method into this method (make sure you don't delete
the data of any of
+ * the nodes returned from this method!) and continue in this fashion until
the node returned by
+ * this method is <code>null</code>.
+ *
+ * <p>The TSTNode instance returned by this method will be next node to be
operated on by <code>
+ * deleteNodeRecursion</code> (This emulates recursive method call while
avoiding the JVM overhead
+ * normally associated with a recursive method.)
+ *
+ * @param currentNode The node to delete.
+ * @return The next node to be called in deleteNodeRecursion.
+ */
+ private TSTNode deleteNodeRecursion(TSTNode currentNode) {
+ if (currentNode == null) {
+ return null;
+ }
+ if (currentNode.relatives[TSTNode.EQKID] != null || currentNode.data !=
null) {
+ return null;
+ }
+ // can't delete this node if it has a non-null eq kid or data
+ TSTNode currentParent = currentNode.relatives[TSTNode.PARENT];
+ boolean lokidNull = currentNode.relatives[TSTNode.LOKID] == null;
+ boolean hikidNull = currentNode.relatives[TSTNode.HIKID] == null;
+ int childType;
+ if (currentParent.relatives[TSTNode.LOKID] == currentNode) {
+ childType = TSTNode.LOKID;
+ } else if (currentParent.relatives[TSTNode.EQKID] == currentNode) {
+ childType = TSTNode.EQKID;
+ } else if (currentParent.relatives[TSTNode.HIKID] == currentNode) {
+ childType = TSTNode.HIKID;
+ } else {
+ rootNode = null;
+ return null;
+ }
+ if (lokidNull && hikidNull) {
+ currentParent.relatives[childType] = null;
+ return currentParent;
+ }
+ if (lokidNull) {
+ currentParent.relatives[childType] =
currentNode.relatives[TSTNode.HIKID];
+ currentNode.relatives[TSTNode.HIKID].relatives[TSTNode.PARENT] =
currentParent;
+ return currentParent;
+ }
+ if (hikidNull) {
+ currentParent.relatives[childType] =
currentNode.relatives[TSTNode.LOKID];
+ currentNode.relatives[TSTNode.LOKID].relatives[TSTNode.PARENT] =
currentParent;
+ return currentParent;
+ }
+ int deltaHi = currentNode.relatives[TSTNode.HIKID].splitchar -
currentNode.splitchar;
+ int deltaLo = currentNode.splitchar -
currentNode.relatives[TSTNode.LOKID].splitchar;
+ int movingKid;
+ TSTNode targetNode;
+ if (deltaHi == deltaLo) {
+ if (Math.random() < 0.5) {
+ deltaHi++;
+ } else {
+ deltaLo++;
+ }
+ }
+ if (deltaHi > deltaLo) {
+ movingKid = TSTNode.HIKID;
+ targetNode = currentNode.relatives[TSTNode.LOKID];
+ } else {
+ movingKid = TSTNode.LOKID;
+ targetNode = currentNode.relatives[TSTNode.HIKID];
+ }
+ while (targetNode.relatives[movingKid] != null) {
+ targetNode = targetNode.relatives[movingKid];
+ }
+ targetNode.relatives[movingKid] = currentNode.relatives[movingKid];
+ currentParent.relatives[childType] = targetNode;
+ targetNode.relatives[TSTNode.PARENT] = currentParent;
+ if (!lokidNull) {
+ currentNode.relatives[TSTNode.LOKID] = null;
+ }
+ if (!hikidNull) {
+ currentNode.relatives[TSTNode.HIKID] = null;
+ }
+ return currentParent;
+ }
+
+ /**
+ * Retrieve the object indexed by a key.
+ *
+ * @param key A <code>String</code> index.
+ * @return The object retrieved from the Ternary Search Trie.
+ */
+ public Object get(CharSequence key) {
+ TSTNode node = getNode(key);
+ if (node == null) {
+ return null;
+ }
+ return node.data;
+ }
+
+ /**
+ * Retrieve the <code>Float</code> indexed by key, increment it by one unit
and store the new
+ * <code>Float</code>.
+ *
+ * @param key A <code>String</code> index.
+ * @return The <code>Float</code> retrieved from the Ternary Search Trie.
+ */
+ public Float getAndIncrement(String key) {
+ String key2 = key.trim().toLowerCase(locale);
+ TSTNode node = getNode(key2);
+ if (node == null) {
+ return null;
+ }
+ Float aux = (Float) (node.data);
+ if (aux == null) {
+ aux = 1f;
+ } else {
+ aux = (float) (aux.intValue() + 1);
+ }
+ put(key2, aux);
+ return aux;
+ }
+
+ /**
+ * Returns the key that indexes the node argument.
+ *
+ * @param node The node whose index is to be calculated.
+ * @return The <code>String</code> that indexes the node argument.
+ */
+ protected String getKey(TSTNode node) {
+ StringBuilder getKeyBuffer = new StringBuilder();
+ getKeyBuffer.setLength(0);
+ getKeyBuffer.append("").append(node.splitchar);
+ TSTNode currentNode;
+ TSTNode lastNode;
+ currentNode = node.relatives[TSTNode.PARENT];
+ lastNode = node;
+ while (currentNode != null) {
+ if (currentNode.relatives[TSTNode.EQKID] == lastNode) {
+ getKeyBuffer.append("").append(currentNode.splitchar);
+ }
+ lastNode = currentNode;
+ currentNode = currentNode.relatives[TSTNode.PARENT];
+ }
+ getKeyBuffer.reverse();
+ return getKeyBuffer.toString();
+ }
+
+ /**
+ * Returns the node indexed by key, or <code>null</code> if that node
doesn't exist. Search begins
+ * at root node.
+ *
+ * @param key A <code>String</code> that indexes the node that is returned.
+ * @return The node object indexed by key. This object is an instance of an
inner class named
+ * <code>TernarySearchTrie.TSTNode</code>.
+ */
+ public TSTNode getNode(CharSequence key) {
+ return getNode(key, rootNode);
+ }
+
+ /**
+ * Returns the node indexed by key, or <code>null</code> if that node
doesn't exist. The search
+ * begins at root node.
+ *
+ * @param key A <code>String</code> that indexes the node that is returned.
+ * @param startNode The top node defining the subtrie to be searched.
+ * @return The node object indexed by key. This object is an instance of an
inner class named
+ * <code>TernarySearchTrie.TSTNode</code>.
+ */
+ protected TSTNode getNode(CharSequence key, TSTNode startNode) {
+ if (key == null || startNode == null || key.length() == 0) {
+ return null;
+ }
+ TSTNode currentNode = startNode;
+ int charIndex = 0;
+ while (true) {
+ if (currentNode == null) {
+ return null;
+ }
+ int charComp = compareCharsAlphabetically(key.charAt(charIndex),
currentNode.splitchar);
+ if (charComp == 0) {
+ charIndex++;
+ if (charIndex == key.length()) {
+ return currentNode;
+ }
+ currentNode = currentNode.relatives[TSTNode.EQKID];
+ } else if (charComp < 0) {
+ currentNode = currentNode.relatives[TSTNode.LOKID];
+ } else {
+ currentNode = currentNode.relatives[TSTNode.HIKID];
+ }
+ }
+ }
+
+ /**
+ * Returns the node indexed by key, creating that node if it doesn't exist,
and creating any
+ * required intermediate nodes if they don't exist.
+ *
+ * @param key A <code>String</code> that indexes the node that is returned.
+ * @return The node object indexed by key. This object is an instance of an
inner class named
+ * <code>TernarySearchTrie.TSTNode</code>.
+ * @exception NullPointerException If the key is <code>null</code>.
+ * @exception IllegalArgumentException If the key is an empty
<code>String</code>.
+ */
+ protected TSTNode getOrCreateNode(CharSequence key)
+ throws NullPointerException, IllegalArgumentException {
+ if (key == null) {
+ throw new NullPointerException("attempt to get or create node with null
key");
+ }
+ if (key.length() == 0) {
+ throw new IllegalArgumentException("attempt to get or create node with
key of zero length");
+ }
+ if (rootNode == null) {
+ rootNode = new TSTNode(key.charAt(0), null);
+ }
+ TSTNode currentNode = rootNode;
+ int charIndex = 0;
+ while (true) {
+ int charComp = compareCharsAlphabetically(key.charAt(charIndex),
currentNode.splitchar);
+ if (charComp == 0) {
+ charIndex++;
+ if (charIndex == key.length()) {
+ return currentNode;
+ }
+ if (currentNode.relatives[TSTNode.EQKID] == null) {
+ currentNode.relatives[TSTNode.EQKID] = new
TSTNode(key.charAt(charIndex), currentNode);
+ }
+ currentNode = currentNode.relatives[TSTNode.EQKID];
+ } else if (charComp < 0) {
+ if (currentNode.relatives[TSTNode.LOKID] == null) {
+ currentNode.relatives[TSTNode.LOKID] = new
TSTNode(key.charAt(charIndex), currentNode);
+ }
+ currentNode = currentNode.relatives[TSTNode.LOKID];
+ } else {
+ if (currentNode.relatives[TSTNode.HIKID] == null) {
+ currentNode.relatives[TSTNode.HIKID] = new
TSTNode(key.charAt(charIndex), currentNode);
+ }
+ currentNode = currentNode.relatives[TSTNode.HIKID];
+ }
+ }
+ }
+
+ /**
+ * Returns a <code>List</code> of keys that almost match the argument key.
Keys returned will have
+ * exactly diff characters that do not match the target key, where diff is
equal to the last value
+ * passed in as an argument to the <code>setMatchAlmostDiff</code> method.
+ *
+ * <p>If the <code>matchAlmost</code> method is called before the
<code>setMatchAlmostDiff</code>
+ * method has been called for the first time, then diff = 0.
+ *
+ * @param key The target key.
+ * @return A <code>List</code> with the results.
+ */
+ public List<String> matchAlmost(String key) {
+ return matchAlmost(key, defaultNumReturnValues);
+ }
+
+ /**
+ * Returns a <code>List</code> of keys that almost match the argument key.
Keys returned will have
+ * exactly diff characters that do not match the target key, where diff is
equal to the last value
+ * passed in as an argument to the <code>setMatchAlmostDiff</code> method.
+ *
+ * <p>If the <code>matchAlmost</code> method is called before the
<code>setMatchAlmostDiff</code>
+ * method has been called for the first time, then diff = 0.
+ *
+ * @param key The target key.
+ * @param numReturnValues The maximum number of values returned by this
method.
+ * @return A <code>List</code> with the results
+ */
+ public List<String> matchAlmost(CharSequence key, int numReturnValues) {
+ return matchAlmostRecursion(
+ rootNode,
+ 0,
+ matchAlmostDiff,
+ key,
+ ((numReturnValues < 0) ? -1 : numReturnValues),
+ new Vector<String>(),
+ false);
+ }
+
+ /**
+ * Recursivelly vists the nodes in order to find the ones that almost match
a given key.
+ *
+ * @param currentNode The current node.
+ * @param charIndex The current char.
+ * @param d The number of differences so far.
+ * @param matchAlmostNumReturnValues The maximum number of values in the
result <code>List</code>.
+ * @param matchAlmostResult2 The results so far.
+ * @param upTo If true all keys having up to and including matchAlmostDiff
mismatched letters will
+ * be included in the result (including a key that is exactly the same
as the target string)
+ * otherwise keys will be included in the result only if they have
exactly matchAlmostDiff
+ * number of mismatched letters.
+ * @param matchAlmostKey The key being searched.
+ * @return A <code>List</code> with the results.
+ */
+ private List<String> matchAlmostRecursion(
+ TSTNode currentNode,
+ int charIndex,
+ int d,
+ CharSequence matchAlmostKey,
+ int matchAlmostNumReturnValues,
+ List<String> matchAlmostResult2,
+ boolean upTo) {
+ if ((currentNode == null)
+ || (matchAlmostNumReturnValues != -1
+ && matchAlmostResult2.size() >= matchAlmostNumReturnValues)
+ || (d < 0)
+ || (charIndex >= matchAlmostKey.length())) {
+ return matchAlmostResult2;
+ }
+ int charComp =
+ compareCharsAlphabetically(matchAlmostKey.charAt(charIndex),
currentNode.splitchar);
+ List<String> matchAlmostResult = matchAlmostResult2;
+ if ((d > 0) || (charComp < 0)) {
+ matchAlmostResult =
+ matchAlmostRecursion(
+ currentNode.relatives[TSTNode.LOKID],
+ charIndex,
+ d,
+ matchAlmostKey,
+ matchAlmostNumReturnValues,
+ matchAlmostResult,
+ upTo);
+ }
+ int nextD = (charComp == 0) ? d : d - 1;
+ boolean cond = (upTo) ? (nextD >= 0) : (nextD == 0);
+ if ((matchAlmostKey.length() == charIndex + 1) && cond &&
(currentNode.data != null)) {
+ matchAlmostResult.add(getKey(currentNode));
+ }
+ matchAlmostResult =
+ matchAlmostRecursion(
+ currentNode.relatives[TSTNode.EQKID],
+ charIndex + 1,
+ nextD,
+ matchAlmostKey,
+ matchAlmostNumReturnValues,
+ matchAlmostResult,
+ upTo);
+ if ((d > 0) || (charComp > 0)) {
+ matchAlmostResult =
+ matchAlmostRecursion(
+ currentNode.relatives[TSTNode.HIKID],
+ charIndex,
+ d,
+ matchAlmostKey,
+ matchAlmostNumReturnValues,
+ matchAlmostResult,
+ upTo);
+ }
+ return matchAlmostResult;
+ }
+
+ /**
+ * Returns an alphabetical <code>List</code> of all keys in the trie that
begin with a given
+ * prefix. Only keys for nodes having non-null data are included in the
<code>List</code>.
+ *
+ * @param prefix Each key returned from this method will begin with the
characters in prefix.
+ * @return A <code>List</code> with the results.
+ */
+ public List<String> matchPrefix(String prefix) {
+ return matchPrefix(prefix, defaultNumReturnValues);
+ }
+
+ /**
+ * Returns an alphabetical <code>List</code> of all keys in the trie that
begin with a given
+ * prefix. Only keys for nodes having non-null data are included in the
<code>List</code>.
+ *
+ * @param prefix Each key returned from this method will begin with the
characters in prefix.
+ * @param numReturnValues The maximum number of values returned from this
method.
+ * @return A <code>List</code> with the results
+ */
+ public List<String> matchPrefix(CharSequence prefix, int numReturnValues) {
+ Vector<String> sortKeysResult = new Vector<>();
+ TSTNode startNode = getNode(prefix);
+ if (startNode == null) {
+ return sortKeysResult;
+ }
+ if (startNode.data != null) {
+ sortKeysResult.addElement(getKey(startNode));
+ }
+ return sortKeysRecursion(
+ startNode.relatives[TSTNode.EQKID],
+ ((numReturnValues < 0) ? -1 : numReturnValues),
+ sortKeysResult);
+ }
+
+ /**
+ * Returns the number of nodes in the trie that have non-null data.
+ *
+ * @return The number of nodes in the trie that have non-null data.
+ */
+ public int numDataNodes() {
+ return numDataNodes(rootNode);
+ }
+
+ /**
+ * Returns the number of nodes in the subtrie below and including the
starting node. The method
+ * counts only nodes that have non-null data.
+ *
+ * @param startingNode The top node of the subtrie. the node that defines
the subtrie.
+ * @return The total number of nodes in the subtrie.
+ */
+ protected int numDataNodes(TSTNode startingNode) {
+ return recursiveNodeCalculator(startingNode, true, 0);
+ }
+
+ /**
+ * Returns the total number of nodes in the trie. The method counts nodes
whether or not they have
+ * data.
+ *
+ * @return The total number of nodes in the trie.
+ */
+ public int numNodes() {
+ return numNodes(rootNode);
+ }
+
+ /**
+ * Returns the total number of nodes in the subtrie below and including the
starting Node. The
+ * method counts nodes whether or not they have data.
+ *
+ * @param startingNode The top node of the subtrie. The node that defines
the subtrie.
+ * @return The total number of nodes in the subtrie.
+ */
+ protected int numNodes(TSTNode startingNode) {
+ return recursiveNodeCalculator(startingNode, false, 0);
+ }
+
+ /**
+ * Stores a value in the trie. The value may be retrieved using the key.
+ *
+ * @param key A <code>String</code> that indexes the object to be stored.
+ * @param value The object to be stored in the Trie.
+ */
+ public void put(CharSequence key, Object value) {
+ getOrCreateNode(key).data = value;
+ }
+
+ /**
+ * Recursivelly visists each node to calculate the number of nodes.
+ *
+ * @param currentNode The current node.
+ * @param checkData If true we check the data to be different of
<code>null</code>.
+ * @param numNodes2 The number of nodes so far.
+ * @return The number of nodes accounted.
+ */
+ private int recursiveNodeCalculator(TSTNode currentNode, boolean checkData,
int numNodes2) {
+ if (currentNode == null) {
+ return numNodes2;
+ }
+ int numNodes =
+ recursiveNodeCalculator(currentNode.relatives[TSTNode.LOKID],
checkData, numNodes2);
+ numNodes = recursiveNodeCalculator(currentNode.relatives[TSTNode.EQKID],
checkData, numNodes);
+ numNodes = recursiveNodeCalculator(currentNode.relatives[TSTNode.HIKID],
checkData, numNodes);
+ if (checkData) {
+ if (currentNode.data != null) {
+ numNodes++;
+ }
+ } else {
+ numNodes++;
+ }
+ return numNodes;
+ }
+
+ /**
+ * Removes the value indexed by key. Also removes all nodes that are
rendered unnecessary by the
+ * removal of this data.
+ *
+ * @param key A <code>string</code> that indexes the object to be removed
from the Trie.
+ */
+ public void remove(String key) {
+ deleteNode(getNode(key.trim().toLowerCase(locale)));
+ }
+
+ /**
+ * Sets the number of characters by which words can differ from target word
when calling the
+ * <code>matchAlmost</code> method.
+ *
+ * <p>Arguments less than 0 will set the char difference to 0, and arguments
greater than 3 will
+ * set the char difference to 3.
+ *
+ * @param diff The number of characters by which words can differ from
target word.
+ */
+ public void setMatchAlmostDiff(int diff) {
+ if (diff < 0) {
+ matchAlmostDiff = 0;
+ } else if (diff > 3) {
+ matchAlmostDiff = 3;
+ } else {
+ matchAlmostDiff = diff;
+ }
+ }
+
+ /**
+ * Sets the default maximum number of values returned from the
<code>matchPrefix</code> and <code>
+ * matchAlmost</code> methods.
+ *
+ * <p>The value should be set this to -1 to get an unlimited number of
return values. note that
+ * the methods mentioned above provide overloaded versions that allow you to
specify the maximum
+ * number of return values, in which case this value is temporarily
overridden.
+ *
+ * <p>*@param num The number of values that will be returned when calling
the methods above.
+ */
+ public void setNumReturnValues(int num) {
+ defaultNumReturnValues = (num < 0) ? -1 : num;
+ }
+
+ /**
+ * Returns keys sorted in alphabetical order. This includes the start Node
and all nodes connected
+ * to the start Node.
+ *
+ * <p>The number of keys returned is limited to numReturnValues. To get a
list that isn't limited
+ * in size, set numReturnValues to -1.
+ *
+ * @param startNode The top node defining the subtrie to be searched.
+ * @param numReturnValues The maximum number of values returned from this
method.
+ * @return A <code>List</code> with the results.
+ */
+ protected List<String> sortKeys(TSTNode startNode, int numReturnValues) {
+ return sortKeysRecursion(
+ startNode, ((numReturnValues < 0) ? -1 : numReturnValues), new
Vector<String>());
+ }
+
+ /**
+ * Returns keys sorted in alphabetical order. This includes the current Node
and all nodes
+ * connected to the current Node.
+ *
+ * <p>Sorted keys will be appended to the end of the resulting
<code>List</code>. The result may
+ * be empty when this method is invoked, but may not be <code>null</code>.
+ *
+ * @param currentNode The current node.
+ * @param sortKeysNumReturnValues The maximum number of values in the result.
+ * @param sortKeysResult2 The results so far.
+ * @return A <code>List</code> with the results.
+ */
+ private List<String> sortKeysRecursion(
+ TSTNode currentNode, int sortKeysNumReturnValues, List<String>
sortKeysResult2) {
+ if (currentNode == null) {
+ return sortKeysResult2;
+ }
+ List<String> sortKeysResult =
+ sortKeysRecursion(
+ currentNode.relatives[TSTNode.LOKID], sortKeysNumReturnValues,
sortKeysResult2);
+ if (sortKeysNumReturnValues != -1 && sortKeysResult.size() >=
sortKeysNumReturnValues) {
+ return sortKeysResult;
+ }
+ if (currentNode.data != null) {
+ sortKeysResult.add(getKey(currentNode));
+ }
+ sortKeysResult =
+ sortKeysRecursion(
+ currentNode.relatives[TSTNode.EQKID], sortKeysNumReturnValues,
sortKeysResult);
+ return sortKeysRecursion(
+ currentNode.relatives[TSTNode.HIKID], sortKeysNumReturnValues,
sortKeysResult);
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long mem = RamUsageEstimator.shallowSizeOf(this);
+ final TSTNode root = getRoot();
+ if (root != null) {
+ mem += root.ramBytesUsed();
+ }
+ return mem;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/package-info.java
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/package-info.java
index 569fe8e..f8d3b77 100644
---
a/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/package-info.java
+++
b/solr/core/src/java/org/apache/solr/spelling/suggest/jaspell/package-info.java
@@ -16,7 +16,7 @@
*/
/**
- * Factories for {@linkplain org.apache.lucene.search.suggest.jaspell JaSpell}
based {@link org.apache.solr.spelling.suggest.Suggester}s
+ * Factories for {@linkplain org.apache.solr.spelling.suggest.jaspell JaSpell}
based {@link org.apache.solr.spelling.suggest.Suggester}s
*/
package org.apache.solr.spelling.suggest.jaspell;
diff --git a/solr/core/src/java/org/apache/solr/util/PayloadUtils.java
b/solr/core/src/java/org/apache/solr/util/PayloadUtils.java
index 7bcfd73..7db4562 100644
--- a/solr/core/src/java/org/apache/solr/util/PayloadUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/PayloadUtils.java
@@ -35,10 +35,11 @@ import
org.apache.lucene.queries.payloads.MinPayloadFunction;
import org.apache.lucene.queries.payloads.PayloadDecoder;
import org.apache.lucene.queries.payloads.PayloadFunction;
import org.apache.lucene.queries.payloads.SumPayloadFunction;
-import org.apache.lucene.search.spans.SpanNearQuery;
-import org.apache.lucene.search.spans.SpanOrQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
+
+import org.apache.lucene.queries.spans.SpanNearQuery;
+import org.apache.lucene.queries.spans.SpanOrQuery;
+import org.apache.lucene.queries.spans.SpanQuery;
+import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.schema.FieldType;
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-bm25.xml
b/solr/core/src/test-files/solr/collection1/conf/schema-bm25.xml
index 02a0d08..a9c2a6a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-bm25.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-bm25.xml
@@ -35,6 +35,7 @@
<float name="b">0.76</float>
</similarity>
</fieldType>
+
<field name="id" type="string" indexed="true" stored="true"
multiValued="false" required="false"/>
<field name="text" type="text" indexed="true" stored="false"/>
diff --git
a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
index 4a58100..3494db0 100644
---
a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
+++
b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
@@ -25,7 +25,7 @@
<indexConfig>
<useCompoundFile>${useCompoundFile:false}</useCompoundFile>
<mergePolicyFactory class="org.apache.solr.index.TieredMergePolicyFactory">
- <int name="maxMergeAtOnceExplicit">19</int>
+ <int name="maxMergeAtOnce">19</int>
<int name="maxMergeAtOnce">7</int>
<int name="segmentsPerTier">9</int>
<double name="noCFSRatio">0.1</double>
diff --git
a/solr/core/src/test/org/apache/solr/analysis/TestLuceneMatchVersion.java
b/solr/core/src/test/org/apache/solr/analysis/TestLuceneMatchVersion.java
index 859f141..2f6f856 100644
--- a/solr/core/src/test/org/apache/solr/analysis/TestLuceneMatchVersion.java
+++ b/solr/core/src/test/org/apache/solr/analysis/TestLuceneMatchVersion.java
@@ -52,6 +52,5 @@ public class TestLuceneMatchVersion extends SolrTestCaseJ4 {
type = schema.getFieldType("textTurkishAnalyzerDefault");
Analyzer ana1 = type.getIndexAnalyzer();
assertTrue(ana1 instanceof TurkishAnalyzer);
- assertEquals(DEFAULT_VERSION, ana1.getVersion());
}
}
diff --git
a/solr/core/src/test/org/apache/solr/analysis/TestReversedWildcardFilterFactory.java
b/solr/core/src/test/org/apache/solr/analysis/TestReversedWildcardFilterFactory.java
index e442055..19ac6fc 100644
---
a/solr/core/src/test/org/apache/solr/analysis/TestReversedWildcardFilterFactory.java
+++
b/solr/core/src/test/org/apache/solr/analysis/TestReversedWildcardFilterFactory.java
@@ -170,7 +170,7 @@ public class TestReversedWildcardFilterFactory extends
SolrTestCaseJ4 {
}
Automaton automaton = ((AutomatonQuery) q).getAutomaton();
String prefix =
Operations.getCommonPrefix(Operations.determinize(automaton,
- Operations.DEFAULT_MAX_DETERMINIZED_STATES));
+ Operations.DEFAULT_DETERMINIZE_WORK_LIMIT));
return prefix.length() > 0 && prefix.charAt(0) == '\u0001';
}
diff --git a/solr/core/src/test/org/apache/solr/core/TestMergePolicyConfig.java
b/solr/core/src/test/org/apache/solr/core/TestMergePolicyConfig.java
index 5f4eb95..bf004af 100644
--- a/solr/core/src/test/org/apache/solr/core/TestMergePolicyConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestMergePolicyConfig.java
@@ -110,7 +110,6 @@ public class TestMergePolicyConfig extends SolrTestCaseJ4 {
assertEquals(7, tieredMP.getMaxMergeAtOnce());
// mp-specific setters
- assertEquals(19, tieredMP.getMaxMergeAtOnceExplicit());
assertEquals(0.1D, tieredMP.getNoCFSRatio(), 0.0D);
// make sure we overrode segmentsPerTier
// (split from maxMergeAtOnce out of mergeFactor)
diff --git
a/solr/core/src/test/org/apache/solr/handler/TestSnapshotCoreBackup.java
b/solr/core/src/test/org/apache/solr/handler/TestSnapshotCoreBackup.java
index c096dd1..81f5a1b 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestSnapshotCoreBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestSnapshotCoreBackup.java
@@ -379,7 +379,7 @@ public class TestSnapshotCoreBackup extends SolrTestCaseJ4 {
new File(backup, expectedSegmentsFileName).exists());
}
try (Directory dir = FSDirectory.open(backup.toPath())) {
- TestUtil.checkIndex(dir, true, true, null);
+ TestUtil.checkIndex(dir, true, true, true, null);
try (DirectoryReader r = DirectoryReader.open(dir)) {
assertEquals("numDocs in " + backup.toString(),
numDocs, r.numDocs());
diff --git
a/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
b/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
index 2d760e6..43b2436 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestStressThreadBackup.java
@@ -316,7 +316,7 @@ public class TestStressThreadBackup extends
SolrCloudTestCase {
final int numRealDocsExpected = Integer.parseInt(m.group());
try (Directory dir = FSDirectory.open(backup.toPath())) {
- TestUtil.checkIndex(dir, true, true, null);
+ TestUtil.checkIndex(dir, true, true, true, null);
try (DirectoryReader r = DirectoryReader.open(dir)) {
assertEquals("num real docs in " + backup.toString(),
numRealDocsExpected, r.docFreq(new
Term("type_s","real")));
diff --git a/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
b/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
index 0deb6a2..0513fd9 100644
--- a/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
+++ b/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
@@ -28,9 +28,9 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.params.HighlightParams;
diff --git
a/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java
b/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java
index 32795f4..aa0b868 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java
@@ -38,7 +38,6 @@ import
org.apache.solr.client.solrj.request.schema.SchemaRequest;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
-import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SimilarityFactory;
import org.apache.solr.search.similarities.SchemaSimilarityFactory;
import org.apache.solr.util.RESTfulServerProvider;
@@ -203,7 +202,7 @@ public class TestBulkSchemaAPI extends RestTestBase {
@SuppressWarnings({"rawtypes"})
Map analyzer = (Map)map.get("analyzer");
assertEquals("org.apache.lucene.analysis.core.WhitespaceAnalyzer",
String.valueOf(analyzer.get("class")));
- assertEquals("5.0.0",
String.valueOf(analyzer.get(IndexSchema.LUCENE_MATCH_VERSION_PARAM)));
+
}
public void testAnalyzerByName() throws Exception {
diff --git
a/solr/core/src/test/org/apache/solr/search/ApacheLuceneSolrNearQueryBuilder.java
b/solr/core/src/test/org/apache/solr/search/ApacheLuceneSolrNearQueryBuilder.java
index 574a736..01c1e63 100644
---
a/solr/core/src/test/org/apache/solr/search/ApacheLuceneSolrNearQueryBuilder.java
+++
b/solr/core/src/test/org/apache/solr/search/ApacheLuceneSolrNearQueryBuilder.java
@@ -18,13 +18,13 @@ package org.apache.solr.search;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.spans.SpanNearQuery;
+import org.apache.lucene.queries.spans.SpanQuery;
+import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.queryparser.xml.builders.SpanQueryBuilder;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanNearQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.solr.request.SolrQueryRequest;
import org.w3c.dom.Element;
diff --git
a/solr/core/src/test/org/apache/solr/search/ChooseOneWordQueryBuilder.java
b/solr/core/src/test/org/apache/solr/search/ChooseOneWordQueryBuilder.java
index 6e2112e..3fd29ed 100644
--- a/solr/core/src/test/org/apache/solr/search/ChooseOneWordQueryBuilder.java
+++ b/solr/core/src/test/org/apache/solr/search/ChooseOneWordQueryBuilder.java
@@ -18,13 +18,13 @@ package org.apache.solr.search;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.spans.SpanQuery;
+import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.queryparser.xml.builders.SpanQueryBuilder;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.solr.request.SolrQueryRequest;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
diff --git a/solr/core/src/test/org/apache/solr/search/FuzzySearchTest.java
b/solr/core/src/test/org/apache/solr/search/FuzzySearchTest.java
deleted file mode 100644
index f84cf10..0000000
--- a/solr/core/src/test/org/apache/solr/search/FuzzySearchTest.java
+++ /dev/null
@@ -1,67 +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.solr.search;
-
-import java.io.IOException;
-
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.solr.client.solrj.SolrQuery;
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.impl.BaseHttpSolrClient;
-import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.cloud.SolrCloudTestCase;
-import org.apache.solr.common.SolrInputDocument;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
[email protected]
-public class FuzzySearchTest extends SolrCloudTestCase {
- private final static String COLLECTION = "c1";
- private CloudSolrClient client;
-
- @BeforeClass
- public static void setupCluster() throws Exception {
- configureCluster(1).addConfig(COLLECTION,
configset("cloud-minimal")).configure();
- }
-
- @Before
- public void setupCollection() throws Exception {
- client = cluster.getSolrClient();
- client.setDefaultCollection(COLLECTION);
-
- CollectionAdminRequest.createCollection(COLLECTION, 1, 1).process(client);
- cluster.waitForActiveCollection(COLLECTION, 1, 1);
- }
-
- @Test
- public void testTooComplex() throws IOException, SolrServerException {
- SolrInputDocument doc = new SolrInputDocument();
-
- doc.setField("id", "1");
- doc.setField("text", "foo");
- client.add(doc);
- client.commit(); // Must have index files written, but the contents don't
matter
-
- SolrQuery query = new
SolrQuery("text:headquarters\\(在日米海軍横須賀基地司令部庁舎\\/旧横須賀鎮守府会議所・横須賀海軍艦船部\\)~");
-
- BaseHttpSolrClient.RemoteSolrException e =
expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () ->
client.query(query));
- assertTrue("Should be client error, not server error", e.code() >= 400 &&
e.code() < 500);
- }
-}
diff --git a/solr/core/src/test/org/apache/solr/search/HandyQueryBuilder.java
b/solr/core/src/test/org/apache/solr/search/HandyQueryBuilder.java
index f76015f..ae6c620 100644
--- a/solr/core/src/test/org/apache/solr/search/HandyQueryBuilder.java
+++ b/solr/core/src/test/org/apache/solr/search/HandyQueryBuilder.java
@@ -17,14 +17,14 @@
package org.apache.solr.search;
import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queries.spans.SpanOrQuery;
+import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.queryparser.xml.builders.SpanQueryBuilder;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.spans.SpanOrQuery;
-import org.apache.lucene.search.spans.SpanQuery;
import org.apache.solr.request.SolrQueryRequest;
import org.w3c.dom.Element;
diff --git a/solr/core/src/test/org/apache/solr/search/TestDocSet.java
b/solr/core/src/test/org/apache/solr/search/TestDocSet.java
index 8a84f2e..47f481a 100644
--- a/solr/core/src/test/org/apache/solr/search/TestDocSet.java
+++ b/solr/core/src/test/org/apache/solr/search/TestDocSet.java
@@ -288,6 +288,11 @@ public class TestDocSet extends SolrTestCase {
}
@Override
+ public Fields getTermVectors(int docID) {
+ return null;
+ }
+
+ @Override
public int numDocs() {
return maxDoc;
}
@@ -308,11 +313,6 @@ public class TestDocSet extends SolrTestCase {
}
@Override
- public Fields getTermVectors(int doc) {
- return null;
- }
-
- @Override
public NumericDocValues getNumericDocValues(String field) {
return null;
}
@@ -353,7 +353,8 @@ public class TestDocSet extends SolrTestCase {
}
@Override
- public TopDocs searchNearestVectors(String field, float[] target, int k,
int fanout) {
+ public TopDocs searchNearestVectors(String field, float[] target, int k,
Bits acceptDocs)
+ throws IOException {
return null;
}
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
b/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
index d82abdb..def7a21 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrCoreParser.java
@@ -25,6 +25,9 @@ import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.analysis.MockTokenFilter;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.spans.SpanNearQuery;
+import org.apache.lucene.queries.spans.SpanOrQuery;
+import org.apache.lucene.queries.spans.SpanTermQuery;
import org.apache.lucene.queryparser.xml.CoreParser;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.search.BooleanQuery;
@@ -32,11 +35,6 @@ import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.spans.SpanBoostQuery;
-import org.apache.lucene.search.spans.SpanNearQuery;
-import org.apache.lucene.search.spans.SpanOrQuery;
-import org.apache.lucene.search.spans.SpanQuery;
-import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.util.NamedList;
import org.junit.BeforeClass;
@@ -122,12 +120,6 @@ public class TestSolrCoreParser extends SolrTestCaseJ4 {
assertTrue(bq.clauses().get(1).getQuery() instanceof MatchNoDocsQuery);
}
- private static SpanQuery unwrapSpanBoostQuery(Query query) {
- assertTrue(query instanceof SpanBoostQuery);
- final SpanBoostQuery spanBoostQuery = (SpanBoostQuery)query;
- return spanBoostQuery.getQuery();
- }
-
// test custom query (HandyQueryBuilder) wrapping a SpanQuery
public void testHandySpanQuery() throws IOException, ParserException {
final String lhsXml = "<SpanOr fieldName='contents'>"
@@ -146,10 +138,10 @@ public class TestSolrCoreParser extends SolrTestCaseJ4 {
final Query clauseQuery = bq.clauses().get(ii).getQuery();
switch (ii) {
case 0:
- assertTrue(unwrapSpanBoostQuery(clauseQuery) instanceof SpanOrQuery);
+ assertTrue(clauseQuery instanceof SpanOrQuery);
break;
case 1:
- assertTrue(unwrapSpanBoostQuery(clauseQuery) instanceof
SpanNearQuery);
+ assertTrue(clauseQuery instanceof SpanNearQuery);
break;
default:
fail("unexpected clause index "+ii);
@@ -185,8 +177,8 @@ public class TestSolrCoreParser extends SolrTestCaseJ4 {
// the test
final Query query = parseXmlString(xml);
if (span) {
- assertTrue(unwrapSpanBoostQuery(query) instanceof SpanOrQuery);
- final SpanOrQuery soq = (SpanOrQuery)unwrapSpanBoostQuery(query);
+ assertTrue(query instanceof SpanOrQuery);
+ final SpanOrQuery soq = (SpanOrQuery) query;
assertEquals(2, soq.getClauses().length);
checkChooseOneWordQuery(span, soq.getClauses()[0], fieldName,
randomTerms);
checkApacheLuceneSolr(soq.getClauses()[1], fieldName);
diff --git a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
index 4f43b10..63a25ac 100644
--- a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
@@ -92,9 +92,10 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
assertNotNull("null mp", iwc.getMergePolicy());
assertTrue("mp is not TieredMergePolicy", iwc.getMergePolicy() instanceof
TieredMergePolicy);
TieredMergePolicy mp = (TieredMergePolicy) iwc.getMergePolicy();
- assertEquals("mp.maxMergeAtOnceExplicit", 19,
mp.getMaxMergeAtOnceExplicit());
+ assertEquals("mp.maxMergeAtOnce", 7, mp.getMaxMergeAtOnce());
assertEquals("mp.segmentsPerTier",9,(int)mp.getSegmentsPerTier());
+
assertNotNull("null ms", iwc.getMergeScheduler());
assertTrue("ms is not CMS", iwc.getMergeScheduler() instanceof
ConcurrentMergeScheduler);
ConcurrentMergeScheduler ms = (ConcurrentMergeScheduler)
iwc.getMergeScheduler();
diff --git
a/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
b/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
index 78f0eab..24ca22f 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
@@ -625,8 +625,6 @@ public class SchemaTest extends RestTestBase {
assertThat(fieldTypeName,
is(equalTo(newFieldTypeRepresentation.getAttributes().get("name"))));
assertThat(analyzerAttributes.get("class"),
is(equalTo(newFieldTypeRepresentation.getAnalyzer().getAttributes().get("class"))));
- assertThat(analyzerAttributes.get("luceneMatchVersion"),
-
is(equalTo(newFieldTypeRepresentation.getAnalyzer().getAttributes().get("luceneMatchVersion"))));
}
@Test
diff --git a/versions.lock b/versions.lock
index 6960cb0..d3e4025 100644
--- a/versions.lock
+++ b/versions.lock
@@ -132,32 +132,32 @@ org.apache.kerby:kerby-util:1.0.1 (2 constraints:
6518bdb6)
org.apache.logging.log4j:log4j-api:2.14.1 (4 constraints: d033fab0)
org.apache.logging.log4j:log4j-core:2.14.1 (2 constraints: 0d16b624)
org.apache.logging.log4j:log4j-slf4j-impl:2.14.1 (1 constraints: 3a053c3b)
-org.apache.lucene:lucene-analysis-common:9.0.0-prerelease5 (10 constraints:
10cca63a)
-org.apache.lucene:lucene-analysis-icu:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-kuromoji:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-morfologik:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-nori:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-opennlp:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-phonetic:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-smartcn:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-analysis-stempel:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-backward-codecs:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-classification:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-codecs:9.0.0-prerelease5 (3 constraints: 313301b7)
-org.apache.lucene:lucene-core:9.0.0-prerelease5 (26 constraints: a6054f0d)
-org.apache.lucene:lucene-expressions:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-grouping:9.0.0-prerelease5 (2 constraints: f01ea971)
-org.apache.lucene:lucene-highlighter:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-join:9.0.0-prerelease5 (1 constraints: 95093990)
-org.apache.lucene:lucene-memory:9.0.0-prerelease5 (1 constraints: 1f14475c)
-org.apache.lucene:lucene-misc:9.0.0-prerelease5 (1 constraints: 95093990)
-org.apache.lucene:lucene-queries:9.0.0-prerelease5 (5 constraints: 5a5a7a89)
-org.apache.lucene:lucene-queryparser:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-sandbox:9.0.0-prerelease5 (2 constraints: e71d8a14)
-org.apache.lucene:lucene-spatial-extras:9.0.0-prerelease5 (1 constraints:
95093990)
-org.apache.lucene:lucene-spatial3d:9.0.0-prerelease5 (1 constraints: 4215f39f)
-org.apache.lucene:lucene-suggest:9.0.0-prerelease5 (1 constraints: 95093990)
-org.apache.lucene:lucene-test-framework:9.0.0-prerelease5 (1 constraints:
95093990)
+org.apache.lucene:lucene-analysis-common:9.0.0-prerelease9 (10 constraints:
38cc2665)
+org.apache.lucene:lucene-analysis-icu:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-kuromoji:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-morfologik:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-nori:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-opennlp:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-phonetic:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-smartcn:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-analysis-stempel:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-backward-codecs:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-classification:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-codecs:9.0.0-prerelease9 (3 constraints: 3d33d1b9)
+org.apache.lucene:lucene-core:9.0.0-prerelease9 (26 constraints: 0e06b22a)
+org.apache.lucene:lucene-expressions:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-grouping:9.0.0-prerelease9 (2 constraints: f81ea172)
+org.apache.lucene:lucene-highlighter:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-join:9.0.0-prerelease9 (1 constraints: 99093d90)
+org.apache.lucene:lucene-memory:9.0.0-prerelease9 (1 constraints: 23144b5c)
+org.apache.lucene:lucene-misc:9.0.0-prerelease9 (1 constraints: 99093d90)
+org.apache.lucene:lucene-queries:9.0.0-prerelease9 (6 constraints: f06c3251)
+org.apache.lucene:lucene-queryparser:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-sandbox:9.0.0-prerelease9 (2 constraints: ef1d7615)
+org.apache.lucene:lucene-spatial-extras:9.0.0-prerelease9 (1 constraints:
99093d90)
+org.apache.lucene:lucene-spatial3d:9.0.0-prerelease9 (1 constraints: 4615f79f)
+org.apache.lucene:lucene-suggest:9.0.0-prerelease9 (1 constraints: 99093d90)
+org.apache.lucene:lucene-test-framework:9.0.0-prerelease9 (1 constraints:
99093d90)
org.apache.opennlp:opennlp-tools:1.9.1 (2 constraints: a1164d13)
org.apache.pdfbox:fontbox:2.0.17 (1 constraints: 3c05323b)
org.apache.pdfbox:jempbox:1.8.16 (1 constraints: 42054b3b)
@@ -227,8 +227,8 @@ org.locationtech.spatial4j:spatial4j:0.7 (1 constraints:
58105398)
org.openjdk.jmh:jmh-core:1.32 (1 constraints: da04f730)
org.ow2.asm:asm:7.2 (3 constraints: a325a35c)
org.ow2.asm:asm-commons:7.2 (1 constraints: 6b0f7267)
-org.reactivestreams:reactive-streams:1.0.3 (3 constraints: 3c2b02fd)
org.quicktheories:quicktheories:0.26 (1 constraints: dc04f530)
+org.reactivestreams:reactive-streams:1.0.3 (3 constraints: 3c2b02fd)
org.slf4j:jcl-over-slf4j:1.7.24 (1 constraints: 4005473b)
org.slf4j:slf4j-api:1.7.24 (19 constraints: 97f04fc1)
org.tallison:jmatio:1.5 (1 constraints: aa041f2c)
diff --git a/versions.props b/versions.props
index 2c71a28..aac56cf 100644
--- a/versions.props
+++ b/versions.props
@@ -90,7 +90,7 @@ org.apache.httpcomponents:httpmime=4.5.10
org.apache.james:apache-mime4j*=0.8.3
org.apache.kerby:*=1.0.1
org.apache.logging.log4j:*=2.14.1
-org.apache.lucene:*=9.0.0-prerelease5
+org.apache.lucene:*=9.0.0-prerelease9
org.apache.opennlp:opennlp-tools=1.9.1
org.apache.pdfbox:*=2.0.17
org.apache.pdfbox:jempbox=1.8.16