|  | @@ -28,8 +28,11 @@ import org.elasticsearch.index.IndexSettings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.index.mapper.core.TextFieldMapper;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.io.Closeable;
 | 
	
		
			
				|  |  | +import java.util.Arrays;
 | 
	
		
			
				|  |  |  import java.util.HashMap;
 | 
	
		
			
				|  |  | +import java.util.HashSet;
 | 
	
		
			
				|  |  |  import java.util.Map;
 | 
	
		
			
				|  |  | +import java.util.Set;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import static java.util.Collections.unmodifiableMap;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -58,69 +61,34 @@ public class AnalysisService extends AbstractIndexComponent implements Closeable
 | 
	
		
			
				|  |  |          this.tokenFilters = unmodifiableMap(tokenFilterFactoryFactories);
 | 
	
		
			
				|  |  |          analyzerProviders = new HashMap<>(analyzerProviders);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        if (!analyzerProviders.containsKey("default")) {
 | 
	
		
			
				|  |  | -            analyzerProviders.put("default", new StandardAnalyzerProvider(indexSettings, null, "default", Settings.Builder.EMPTY_SETTINGS));
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (!analyzerProviders.containsKey("default_search")) {
 | 
	
		
			
				|  |  | -            analyzerProviders.put("default_search", analyzerProviders.get("default"));
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (!analyzerProviders.containsKey("default_search_quoted")) {
 | 
	
		
			
				|  |  | -            analyzerProviders.put("default_search_quoted", analyzerProviders.get("default_search"));
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        Map<String, NamedAnalyzer> analyzerAliases = new HashMap<>();
 | 
	
		
			
				|  |  |          Map<String, NamedAnalyzer> analyzers = new HashMap<>();
 | 
	
		
			
				|  |  |          for (Map.Entry<String, AnalyzerProvider<?>> entry : analyzerProviders.entrySet()) {
 | 
	
		
			
				|  |  | -            AnalyzerProvider<?> analyzerFactory = entry.getValue();
 | 
	
		
			
				|  |  | -            String name = entry.getKey();
 | 
	
		
			
				|  |  | -            /*
 | 
	
		
			
				|  |  | -             * Lucene defaults positionIncrementGap to 0 in all analyzers but
 | 
	
		
			
				|  |  | -             * Elasticsearch defaults them to 0 only before version 2.0
 | 
	
		
			
				|  |  | -             * and 100 afterwards so we override the positionIncrementGap if it
 | 
	
		
			
				|  |  | -             * doesn't match here.
 | 
	
		
			
				|  |  | -             */
 | 
	
		
			
				|  |  | -            int overridePositionIncrementGap = TextFieldMapper.Defaults.POSITION_INCREMENT_GAP;
 | 
	
		
			
				|  |  | -            if (analyzerFactory instanceof CustomAnalyzerProvider) {
 | 
	
		
			
				|  |  | -                ((CustomAnalyzerProvider) analyzerFactory).build(this);
 | 
	
		
			
				|  |  | -                /*
 | 
	
		
			
				|  |  | -                 * Custom analyzers already default to the correct, version
 | 
	
		
			
				|  |  | -                 * dependent positionIncrementGap and the user is be able to
 | 
	
		
			
				|  |  | -                 * configure the positionIncrementGap directly on the analyzer so
 | 
	
		
			
				|  |  | -                 * we disable overriding the positionIncrementGap to preserve the
 | 
	
		
			
				|  |  | -                 * user's setting.
 | 
	
		
			
				|  |  | -                 */
 | 
	
		
			
				|  |  | -                overridePositionIncrementGap = Integer.MIN_VALUE;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            Analyzer analyzerF = analyzerFactory.get();
 | 
	
		
			
				|  |  | -            if (analyzerF == null) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException("analyzer [" + analyzerFactory.name() + "] created null analyzer");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            NamedAnalyzer analyzer;
 | 
	
		
			
				|  |  | -            if (analyzerF instanceof NamedAnalyzer) {
 | 
	
		
			
				|  |  | -                // if we got a named analyzer back, use it...
 | 
	
		
			
				|  |  | -                analyzer = (NamedAnalyzer) analyzerF;
 | 
	
		
			
				|  |  | -                if (overridePositionIncrementGap >= 0 && analyzer.getPositionIncrementGap(analyzer.name()) != overridePositionIncrementGap) {
 | 
	
		
			
				|  |  | -                    // unless the positionIncrementGap needs to be overridden
 | 
	
		
			
				|  |  | -                    analyzer = new NamedAnalyzer(analyzer, overridePositionIncrementGap);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +            processAnalyzerFactory(entry.getKey(), entry.getValue(), analyzerAliases, analyzers);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (Map.Entry<String, NamedAnalyzer> entry : analyzerAliases.entrySet()) {
 | 
	
		
			
				|  |  | +            String key = entry.getKey();
 | 
	
		
			
				|  |  | +            if (analyzers.containsKey(key) &&
 | 
	
		
			
				|  |  | +                ("default".equals(key) || "default_search".equals(key) || "default_search_quoted".equals(key)) == false) {
 | 
	
		
			
				|  |  | +                throw new IllegalStateException("already registered analyzer with name: " + key);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  | -                analyzer = new NamedAnalyzer(name, analyzerFactory.scope(), analyzerF, overridePositionIncrementGap);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (analyzers.containsKey(name)) {
 | 
	
		
			
				|  |  | -                throw new IllegalStateException("already registered analyzer with name: " + name);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            analyzers.put(name, analyzer);
 | 
	
		
			
				|  |  | -            String strAliases = this.indexSettings.getSettings().get("index.analysis.analyzer." + analyzerFactory.name() + ".alias");
 | 
	
		
			
				|  |  | -            if (strAliases != null) {
 | 
	
		
			
				|  |  | -                for (String alias : Strings.commaDelimitedListToStringArray(strAliases)) {
 | 
	
		
			
				|  |  | -                    analyzers.put(alias, analyzer);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            String[] aliases = this.indexSettings.getSettings().getAsArray("index.analysis.analyzer." + analyzerFactory.name() + ".alias");
 | 
	
		
			
				|  |  | -            for (String alias : aliases) {
 | 
	
		
			
				|  |  | -                analyzers.put(alias, analyzer);
 | 
	
		
			
				|  |  | +                NamedAnalyzer configured = entry.getValue();
 | 
	
		
			
				|  |  | +                analyzers.put(key, configured);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        if (!analyzers.containsKey("default")) {
 | 
	
		
			
				|  |  | +            processAnalyzerFactory("default", new StandardAnalyzerProvider(indexSettings, null, "default", Settings.Builder.EMPTY_SETTINGS),
 | 
	
		
			
				|  |  | +                analyzerAliases, analyzers);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (!analyzers.containsKey("default_search")) {
 | 
	
		
			
				|  |  | +            analyzers.put("default_search", analyzers.get("default"));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (!analyzers.containsKey("default_search_quoted")) {
 | 
	
		
			
				|  |  | +            analyzers.put("default_search_quoted", analyzers.get("default_search"));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          NamedAnalyzer defaultAnalyzer = analyzers.get("default");
 | 
	
		
			
				|  |  |          if (defaultAnalyzer == null) {
 | 
	
		
			
				|  |  |              throw new IllegalArgumentException("no default analyzer configured");
 | 
	
	
		
			
				|  | @@ -145,6 +113,58 @@ public class AnalysisService extends AbstractIndexComponent implements Closeable
 | 
	
		
			
				|  |  |          this.analyzers = unmodifiableMap(analyzers);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    private void processAnalyzerFactory(String name, AnalyzerProvider<?> analyzerFactory, Map<String, NamedAnalyzer> analyzerAliases, Map<String, NamedAnalyzer> analyzers) {
 | 
	
		
			
				|  |  | +        /*
 | 
	
		
			
				|  |  | +         * Lucene defaults positionIncrementGap to 0 in all analyzers but
 | 
	
		
			
				|  |  | +         * Elasticsearch defaults them to 0 only before version 2.0
 | 
	
		
			
				|  |  | +         * and 100 afterwards so we override the positionIncrementGap if it
 | 
	
		
			
				|  |  | +         * doesn't match here.
 | 
	
		
			
				|  |  | +         */
 | 
	
		
			
				|  |  | +        int overridePositionIncrementGap = TextFieldMapper.Defaults.POSITION_INCREMENT_GAP;
 | 
	
		
			
				|  |  | +        if (analyzerFactory instanceof CustomAnalyzerProvider) {
 | 
	
		
			
				|  |  | +            ((CustomAnalyzerProvider) analyzerFactory).build(this);
 | 
	
		
			
				|  |  | +            /*
 | 
	
		
			
				|  |  | +             * Custom analyzers already default to the correct, version
 | 
	
		
			
				|  |  | +             * dependent positionIncrementGap and the user is be able to
 | 
	
		
			
				|  |  | +             * configure the positionIncrementGap directly on the analyzer so
 | 
	
		
			
				|  |  | +             * we disable overriding the positionIncrementGap to preserve the
 | 
	
		
			
				|  |  | +             * user's setting.
 | 
	
		
			
				|  |  | +             */
 | 
	
		
			
				|  |  | +            overridePositionIncrementGap = Integer.MIN_VALUE;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        Analyzer analyzerF = analyzerFactory.get();
 | 
	
		
			
				|  |  | +        if (analyzerF == null) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException("analyzer [" + analyzerFactory.name() + "] created null analyzer");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        NamedAnalyzer analyzer;
 | 
	
		
			
				|  |  | +        if (analyzerF instanceof NamedAnalyzer) {
 | 
	
		
			
				|  |  | +            // if we got a named analyzer back, use it...
 | 
	
		
			
				|  |  | +            analyzer = (NamedAnalyzer) analyzerF;
 | 
	
		
			
				|  |  | +            if (overridePositionIncrementGap >= 0 && analyzer.getPositionIncrementGap(analyzer.name()) != overridePositionIncrementGap) {
 | 
	
		
			
				|  |  | +                // unless the positionIncrementGap needs to be overridden
 | 
	
		
			
				|  |  | +                analyzer = new NamedAnalyzer(analyzer, overridePositionIncrementGap);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            analyzer = new NamedAnalyzer(name, analyzerFactory.scope(), analyzerF, overridePositionIncrementGap);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (analyzers.containsKey(name)) {
 | 
	
		
			
				|  |  | +            throw new IllegalStateException("already registered analyzer with name: " + name);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        analyzers.put(name, analyzer);
 | 
	
		
			
				|  |  | +        String strAliases = this.indexSettings.getSettings().get("index.analysis.analyzer." + analyzerFactory.name() + ".alias");
 | 
	
		
			
				|  |  | +        Set<String> aliases = new HashSet<>();
 | 
	
		
			
				|  |  | +        if (strAliases != null) {
 | 
	
		
			
				|  |  | +            aliases.addAll(Strings.commaDelimitedListToSet(strAliases));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        aliases.addAll(Arrays.asList(this.indexSettings.getSettings()
 | 
	
		
			
				|  |  | +            .getAsArray("index.analysis.analyzer." + analyzerFactory.name() + ".alias")));
 | 
	
		
			
				|  |  | +        for (String alias : aliases) {
 | 
	
		
			
				|  |  | +            if (analyzerAliases.putIfAbsent(alias, analyzer) != null) {
 | 
	
		
			
				|  |  | +                throw new IllegalStateException("alias [" + alias + "] is already used by [" + analyzerAliases.get(alias).name() + "]");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public void close() {
 | 
	
		
			
				|  |  |          for (NamedAnalyzer analyzer : analyzers.values()) {
 |