StableAnalysisPluginsNoSettingsTests.java 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
  3. * or more contributor license agreements. Licensed under the Elastic License
  4. * 2.0 and the Server Side Public License, v 1; you may not use this file except
  5. * in compliance with, at your election, the Elastic License 2.0 or the Server
  6. * Side Public License, v 1.
  7. */
  8. package org.elasticsearch.indices.analysis;
  9. import org.apache.lucene.analysis.Analyzer;
  10. import org.apache.lucene.analysis.TokenStream;
  11. import org.apache.lucene.analysis.Tokenizer;
  12. import org.elasticsearch.cluster.metadata.IndexMetadata;
  13. import org.elasticsearch.common.settings.Settings;
  14. import org.elasticsearch.env.Environment;
  15. import org.elasticsearch.env.TestEnvironment;
  16. import org.elasticsearch.index.IndexService.IndexCreationContext;
  17. import org.elasticsearch.index.IndexSettings;
  18. import org.elasticsearch.index.IndexVersion;
  19. import org.elasticsearch.index.analysis.AnalysisRegistry;
  20. import org.elasticsearch.index.analysis.IndexAnalyzers;
  21. import org.elasticsearch.indices.analysis.lucene.AppendTokenFilter;
  22. import org.elasticsearch.indices.analysis.lucene.CharSkippingTokenizer;
  23. import org.elasticsearch.indices.analysis.lucene.ReplaceCharToNumber;
  24. import org.elasticsearch.indices.analysis.lucene.SkipStartingWithDigitTokenFilter;
  25. import org.elasticsearch.plugin.NamedComponent;
  26. import org.elasticsearch.plugin.analysis.AnalysisMode;
  27. import org.elasticsearch.plugin.analysis.AnalyzerFactory;
  28. import org.elasticsearch.plugin.analysis.CharFilterFactory;
  29. import org.elasticsearch.plugin.analysis.TokenFilterFactory;
  30. import org.elasticsearch.plugin.analysis.TokenizerFactory;
  31. import org.elasticsearch.plugins.scanners.NameToPluginInfo;
  32. import org.elasticsearch.plugins.scanners.NamedComponentReader;
  33. import org.elasticsearch.plugins.scanners.PluginInfo;
  34. import org.elasticsearch.plugins.scanners.StablePluginsRegistry;
  35. import org.elasticsearch.test.ESTestCase;
  36. import org.elasticsearch.test.IndexSettingsModule;
  37. import org.elasticsearch.test.index.IndexVersionUtils;
  38. import java.io.IOException;
  39. import java.io.Reader;
  40. import java.util.List;
  41. import java.util.Map;
  42. import static java.util.Collections.emptyList;
  43. import static org.apache.lucene.tests.analysis.BaseTokenStreamTestCase.assertTokenStreamContents;
  44. import static org.hamcrest.Matchers.equalTo;
  45. public class StableAnalysisPluginsNoSettingsTests extends ESTestCase {
  46. private final Settings emptyNodeSettings = Settings.builder()
  47. .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
  48. .build();
  49. public IndexAnalyzers getIndexAnalyzers(Settings settings) throws IOException {
  50. AnalysisRegistry registry = setupRegistry();
  51. IndexSettings idxSettings = IndexSettingsModule.newIndexSettings("test", settings);
  52. return registry.build(IndexCreationContext.CREATE_INDEX, idxSettings);
  53. }
  54. public void testStablePlugins() throws IOException {
  55. IndexVersion version = IndexVersionUtils.randomVersion(random());
  56. IndexAnalyzers analyzers = getIndexAnalyzers(
  57. Settings.builder()
  58. .put("index.analysis.analyzer.char_filter_test.tokenizer", "standard")
  59. .put("index.analysis.analyzer.char_filter_test.char_filter", "stableCharFilterFactory")
  60. .put("index.analysis.analyzer.token_filter_test.tokenizer", "standard")
  61. .put("index.analysis.analyzer.token_filter_test.filter", "stableTokenFilterFactory")
  62. .put("index.analysis.analyzer.tokenizer_test.tokenizer", "stableTokenizerFactory")
  63. .put("index.analysis.analyzer.analyzer_provider_test.type", "stableAnalyzerFactory")
  64. .put(IndexMetadata.SETTING_VERSION_CREATED, version)
  65. .build()
  66. );
  67. assertTokenStreamContents(analyzers.get("char_filter_test").tokenStream("", "t#st"), new String[] { "t3st" });
  68. assertTokenStreamContents(
  69. analyzers.get("token_filter_test").tokenStream("", "1test 2test 1test 3test "),
  70. new String[] { "2test", "3test" }
  71. );
  72. assertTokenStreamContents(analyzers.get("tokenizer_test").tokenStream("", "x_y_z"), new String[] { "x", "y", "z" });
  73. assertTokenStreamContents(analyzers.get("analyzer_provider_test").tokenStream("", "1x_y_#z"), new String[] { "y", "3z" });
  74. assertThat(analyzers.get("char_filter_test").normalize("", "t#st").utf8ToString(), equalTo("t3st"));
  75. assertThat(
  76. analyzers.get("token_filter_test").normalize("", "1test 2test 1test 3test ").utf8ToString(),
  77. equalTo("1test 2test 1test 3test 1")
  78. );
  79. }
  80. @NamedComponent("stableCharFilterFactory")
  81. public static class TestCharFilterFactory implements CharFilterFactory {
  82. @Override
  83. public Reader create(Reader reader) {
  84. return new ReplaceCharToNumber(reader, "#", 3);
  85. }
  86. @Override
  87. public Reader normalize(Reader reader) {
  88. return new ReplaceCharToNumber(reader, "#", 3);
  89. }
  90. }
  91. @NamedComponent("stableTokenFilterFactory")
  92. public static class TestTokenFilterFactory implements TokenFilterFactory {
  93. @Override
  94. public TokenStream create(TokenStream tokenStream) {
  95. return new SkipStartingWithDigitTokenFilter(tokenStream, 1);
  96. }
  97. @Override
  98. public TokenStream normalize(TokenStream tokenStream) {
  99. return new AppendTokenFilter(tokenStream, "1");
  100. }
  101. @Override
  102. public AnalysisMode getAnalysisMode() {
  103. return TokenFilterFactory.super.getAnalysisMode();
  104. }
  105. }
  106. @NamedComponent("stableTokenizerFactory")
  107. public static class TestTokenizerFactory implements TokenizerFactory {
  108. @Override
  109. public Tokenizer create() {
  110. return new CharSkippingTokenizer(List.of("_"));
  111. }
  112. }
  113. @NamedComponent("stableAnalyzerFactory")
  114. public static class TestAnalyzerFactory implements AnalyzerFactory {
  115. @Override
  116. public Analyzer create() {
  117. return new CustomAnalyzer();
  118. }
  119. static class CustomAnalyzer extends Analyzer {
  120. @Override
  121. protected TokenStreamComponents createComponents(String fieldName) {
  122. var tokenizer = new CharSkippingTokenizer(List.of("_"));
  123. var tokenFilter = new SkipStartingWithDigitTokenFilter(tokenizer, 1);
  124. return new TokenStreamComponents(r -> tokenizer.setReader(new ReplaceCharToNumber(r, "#", 3)), tokenFilter);
  125. }
  126. }
  127. }
  128. private AnalysisRegistry setupRegistry() throws IOException {
  129. ClassLoader classLoader = getClass().getClassLoader();
  130. AnalysisRegistry registry = new AnalysisModule(
  131. TestEnvironment.newEnvironment(emptyNodeSettings),
  132. emptyList(),
  133. new StablePluginsRegistry(
  134. new NamedComponentReader(),
  135. Map.of(
  136. CharFilterFactory.class.getCanonicalName(),
  137. new NameToPluginInfo(
  138. Map.of(
  139. "stableCharFilterFactory",
  140. new PluginInfo("stableCharFilterFactory", TestCharFilterFactory.class.getName(), classLoader)
  141. )
  142. ),
  143. TokenFilterFactory.class.getCanonicalName(),
  144. new NameToPluginInfo(
  145. Map.of(
  146. "stableTokenFilterFactory",
  147. new PluginInfo("stableTokenFilterFactory", TestTokenFilterFactory.class.getName(), classLoader)
  148. )
  149. ),
  150. TokenizerFactory.class.getCanonicalName(),
  151. new NameToPluginInfo(
  152. Map.of(
  153. "stableTokenizerFactory",
  154. new PluginInfo("stableTokenizerFactory", TestTokenizerFactory.class.getName(), classLoader)
  155. )
  156. ),
  157. AnalyzerFactory.class.getCanonicalName(),
  158. new NameToPluginInfo(
  159. Map.of(
  160. "stableAnalyzerFactory",
  161. new PluginInfo("stableAnalyzerFactory", TestAnalyzerFactory.class.getName(), classLoader)
  162. )
  163. )
  164. )
  165. )
  166. ).getAnalysisRegistry();
  167. return registry;
  168. }
  169. }