mirror of https://github.com/apache/lucene.git
LUCENE-8894: Add APIs to tokenizer/charfilter/tokenfilter factories to get their SPI names from concrete classes
This commit is contained in:
parent
2df6ea2305
commit
7e05bd7173
|
@ -111,6 +111,8 @@ Improvements
|
|||
|
||||
* LUCENE-8855: Add Accountable to some Query implementations (ab, Adrien Grand)
|
||||
|
||||
* LUCENE-8894: Add APIs to find SPI names for Tokenizer/CharFilter/TokenFilter factory classes. (Tomoko Uchida)
|
||||
|
||||
Optimizations
|
||||
|
||||
* LUCENE-8796: Use exponential search instead of binary search in
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -32,6 +34,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -336,4 +339,23 @@ public abstract class AbstractAnalysisFactory {
|
|||
public void setExplicitLuceneMatchVersion(boolean isExplicitLuceneMatchVersion) {
|
||||
this.isExplicitLuceneMatchVersion = isExplicitLuceneMatchVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up SPI name (static "NAME" field) with appropriate modifiers.
|
||||
* Also it must be a String class and declared in the concrete class.
|
||||
* @return the SPI name
|
||||
* @throws NoSuchFieldException - if the "NAME" field is not defined.
|
||||
* @throws IllegalAccessException - if the "NAME" field is inaccessible.
|
||||
* @throws IllegalStateException - if the "NAME" field does not have appropriate modifiers or isn't a String field.
|
||||
*/
|
||||
static String lookupSPIName(Class<? extends AbstractAnalysisFactory> service) throws NoSuchFieldException, IllegalAccessException, IllegalStateException {
|
||||
final Field field = service.getField("NAME");
|
||||
int modifier = field.getModifiers();
|
||||
if (Modifier.isStatic(modifier) && Modifier.isFinal(modifier) &&
|
||||
field.getType().equals(String.class) &&
|
||||
Objects.equals(field.getDeclaringClass(), service)) {
|
||||
return ((String) field.get(null));
|
||||
}
|
||||
throw new IllegalStateException("No SPI name defined.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
package org.apache.lucene.analysis.util;
|
||||
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
|
@ -83,21 +81,13 @@ public final class AnalysisSPILoader<S extends AbstractAnalysisFactory> {
|
|||
String originalName = null;
|
||||
Throwable cause = null;
|
||||
try {
|
||||
// Lookup "NAME" field with appropriate modifiers.
|
||||
// Also it must be a String class and declared in the service class.
|
||||
final Field field = service.getField("NAME");
|
||||
int modifier = field.getModifiers();
|
||||
if (Modifier.isStatic(modifier) && Modifier.isFinal(modifier) &&
|
||||
field.getType().equals(String.class) &&
|
||||
Objects.equals(field.getDeclaringClass(), service)) {
|
||||
originalName = ((String)field.get(null));
|
||||
name = originalName.toLowerCase(Locale.ROOT);
|
||||
if (!isValidName(originalName)) {
|
||||
throw new ServiceConfigurationError("The name " + originalName + " for " + service.getName() +
|
||||
" is invalid: Allowed characters are (English) alphabet, digits, and underscore. It should be started with an alphabet.");
|
||||
}
|
||||
originalName = AbstractAnalysisFactory.lookupSPIName(service);
|
||||
name = originalName.toLowerCase(Locale.ROOT);
|
||||
if (!isValidName(originalName)) {
|
||||
throw new ServiceConfigurationError("The name " + originalName + " for " + service.getName() +
|
||||
" is invalid: Allowed characters are (English) alphabet, digits, and underscore. It should be started with an alphabet.");
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalStateException e) {
|
||||
cause = e;
|
||||
}
|
||||
if (name == null) {
|
||||
|
|
|
@ -49,6 +49,15 @@ public abstract class CharFilterFactory extends AbstractAnalysisFactory {
|
|||
return loader.availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified char filter factory */
|
||||
public static String findSPIName(Class<? extends CharFilterFactory> serviceClass) {
|
||||
try {
|
||||
return lookupSPIName(serviceClass);
|
||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalStateException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the factory list from the given {@link ClassLoader}.
|
||||
* Changes to the factories are visible after the method ends, all
|
||||
|
|
|
@ -48,6 +48,15 @@ public abstract class TokenFilterFactory extends AbstractAnalysisFactory {
|
|||
return loader.availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified token filter factory */
|
||||
public static String findSPIName(Class<? extends TokenFilterFactory> serviceClass) {
|
||||
try {
|
||||
return lookupSPIName(serviceClass);
|
||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalStateException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the factory list from the given {@link ClassLoader}.
|
||||
* Changes to the factories are visible after the method ends, all
|
||||
|
|
|
@ -50,6 +50,15 @@ public abstract class TokenizerFactory extends AbstractAnalysisFactory {
|
|||
return loader.availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified tokenizer factory */
|
||||
public static String findSPIName(Class<? extends TokenizerFactory> serviceClass) {
|
||||
try {
|
||||
return lookupSPIName(serviceClass);
|
||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalStateException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the factory list from the given {@link ClassLoader}.
|
||||
* Changes to the factories are visible after the method ends, all
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.analysis.util;
|
||||
|
||||
import org.apache.lucene.analysis.charfilter.HTMLStripCharFilterFactory;
|
||||
import org.apache.lucene.analysis.core.LowerCaseFilterFactory;
|
||||
import org.apache.lucene.analysis.core.WhitespaceTokenizerFactory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestAbstractAnalysisFactory extends LuceneTestCase {
|
||||
|
||||
public void testLookupTokenizerSPIName() throws NoSuchFieldException, IllegalAccessException {
|
||||
assertEquals("whitespace", AbstractAnalysisFactory.lookupSPIName(WhitespaceTokenizerFactory.class));
|
||||
assertEquals("whitespace", TokenizerFactory.findSPIName(WhitespaceTokenizerFactory.class));
|
||||
}
|
||||
|
||||
public void testLookupCharFilterSPIName() throws NoSuchFieldException, IllegalAccessException {
|
||||
assertEquals("htmlStrip", AbstractAnalysisFactory.lookupSPIName(HTMLStripCharFilterFactory.class));
|
||||
assertEquals("htmlStrip", CharFilterFactory.findSPIName(HTMLStripCharFilterFactory.class));
|
||||
}
|
||||
|
||||
public void testLookupTokenFilterSPIName() throws NoSuchFieldException, IllegalAccessException{
|
||||
assertEquals("lowercase", AbstractAnalysisFactory.lookupSPIName(LowerCaseFilterFactory.class));
|
||||
assertEquals("lowercase", TokenFilterFactory.findSPIName(LowerCaseFilterFactory.class));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue