/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.server.es; import com.google.common.collect.ImmutableSortedMap; import java.util.Arrays; import java.util.Locale; import java.util.SortedMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings.Builder; import static org.sonar.server.es.DefaultIndexSettings.ANALYSIS; import static org.sonar.server.es.DefaultIndexSettings.ANALYZED; import static org.sonar.server.es.DefaultIndexSettings.ANALYZER; import static org.sonar.server.es.DefaultIndexSettings.ASCIIFOLDING; import static org.sonar.server.es.DefaultIndexSettings.DELIMITER; import static org.sonar.server.es.DefaultIndexSettings.FILTER; import static org.sonar.server.es.DefaultIndexSettings.INDEX; import static org.sonar.server.es.DefaultIndexSettings.KEYWORD; import static org.sonar.server.es.DefaultIndexSettings.LOWERCASE; import static org.sonar.server.es.DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH; import static org.sonar.server.es.DefaultIndexSettings.MAX_GRAM; import static org.sonar.server.es.DefaultIndexSettings.MINIMUM_NGRAM_LENGTH; import static org.sonar.server.es.DefaultIndexSettings.MIN_GRAM; import static org.sonar.server.es.DefaultIndexSettings.PATTERN; import static org.sonar.server.es.DefaultIndexSettings.PORTER_STEM; import static org.sonar.server.es.DefaultIndexSettings.SEARCH_ANALYZER; import static org.sonar.server.es.DefaultIndexSettings.STANDARD; import static org.sonar.server.es.DefaultIndexSettings.STOP; import static org.sonar.server.es.DefaultIndexSettings.STRING; import static org.sonar.server.es.DefaultIndexSettings.SUB_FIELD_DELIMITER; import static org.sonar.server.es.DefaultIndexSettings.TOKENIZER; import static org.sonar.server.es.DefaultIndexSettings.TRIM; import static org.sonar.server.es.DefaultIndexSettings.TYPE; import static org.sonar.server.es.DefaultIndexSettings.WHITESPACE; public enum DefaultIndexSettingsElement { // Filters WORD_FILTER(FILTER) { @Override protected void setup() { set(TYPE, "word_delimiter"); set("generate_word_parts", true); set("catenate_words", true); set("catenate_numbers", true); set("catenate_all", true); set("split_on_case_change", true); set("preserve_original", true); set("split_on_numerics", true); set("stem_english_possessive", true); } }, NGRAM_FILTER(FILTER) { @Override protected void setup() { set(TYPE, "nGram"); set(MIN_GRAM, MINIMUM_NGRAM_LENGTH); set(MAX_GRAM, MAXIMUM_NGRAM_LENGTH); setArray("token_chars", "letter", "digit", "punctuation", "symbol"); } }, // Tokenizers GRAM_TOKENIZER(TOKENIZER) { @Override protected void setup() { set(TYPE, "nGram"); set(MIN_GRAM, MINIMUM_NGRAM_LENGTH); set(MAX_GRAM, MAXIMUM_NGRAM_LENGTH); setArray("token_chars", "letter", "digit", "punctuation", "symbol"); } }, PREFIX_TOKENIZER(TOKENIZER) { @Override protected void setup() { set(TYPE, "edgeNGram"); set(MIN_GRAM, MINIMUM_NGRAM_LENGTH); set(MAX_GRAM, MAXIMUM_NGRAM_LENGTH); } }, UUID_MODULE_TOKENIZER(TOKENIZER) { @Override protected void setup() { set(TYPE, PATTERN); set(PATTERN, "\\."); } }, // Analyzers SORTABLE_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, KEYWORD); setArray(FILTER, TRIM, LOWERCASE); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, getName()); } }, INDEX_GRAMS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, GRAM_TOKENIZER); setArray(FILTER, TRIM, LOWERCASE); } }, SEARCH_GRAMS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, WHITESPACE); setArray(FILTER, TRIM, LOWERCASE); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, INDEX_GRAMS_ANALYZER.getName(), SEARCH_ANALYZER, getName()); } }, INDEX_PREFIX_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, PREFIX_TOKENIZER); setArray(FILTER, TRIM); } }, SEARCH_PREFIX_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, WHITESPACE); setArray(FILTER, TRIM); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, INDEX_PREFIX_ANALYZER.getName(), SEARCH_ANALYZER, getName()); } }, INDEX_PREFIX_CASE_INSENSITIVE_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, PREFIX_TOKENIZER); setArray(FILTER, TRIM, LOWERCASE); } }, SEARCH_PREFIX_CASE_INSENSITIVE_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, WHITESPACE); setArray(FILTER, TRIM, LOWERCASE); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, INDEX_PREFIX_CASE_INSENSITIVE_ANALYZER.getName(), SEARCH_ANALYZER, getName()); } }, USER_INDEX_GRAMS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, WHITESPACE); setArray(FILTER, TRIM, LOWERCASE, NGRAM_FILTER.getName()); } }, USER_SEARCH_GRAMS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, WHITESPACE); setArray(FILTER, TRIM, LOWERCASE); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, USER_INDEX_GRAMS_ANALYZER.getName(), SEARCH_ANALYZER, getName()); } }, INDEX_WORDS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, STANDARD); setArray(FILTER, STANDARD, "word_filter", LOWERCASE, STOP, ASCIIFOLDING, PORTER_STEM); } }, SEARCH_WORDS_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, STANDARD); setArray(FILTER, STANDARD, LOWERCASE, STOP, ASCIIFOLDING, PORTER_STEM); } @Override public SortedMap<String, String> fieldMapping() { return ImmutableSortedMap.of( TYPE, STRING, INDEX, ANALYZED, ANALYZER, INDEX_WORDS_ANALYZER.getName(), SEARCH_ANALYZER, getName()); } }, ENGLISH_HTML_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, STANDARD); setArray(FILTER, STANDARD, LOWERCASE, STOP, ASCIIFOLDING, PORTER_STEM); setArray("char_filter", "html_strip"); } }, PATH_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, "path_hierarchy"); } }, UUID_MODULE_ANALYZER(ANALYZER) { @Override protected void setup() { set(TOKENIZER, UUID_MODULE_TOKENIZER); setArray(FILTER, TRIM); } }, ; private final String type; private final String name; private Builder builder = Settings.builder(); DefaultIndexSettingsElement(String type) { this.type = type; this.name = name().toLowerCase(Locale.getDefault()); setup(); } protected void set(String settingSuffix, int value) { put(localName(settingSuffix), Integer.toString(value)); } protected void set(String settingSuffix, boolean value) { put(localName(settingSuffix), Boolean.toString(value)); } protected void set(String settingSuffix, DefaultIndexSettingsElement otherElement) { put(localName(settingSuffix), otherElement.name); } protected void set(String settingSuffix, String value) { put(localName(settingSuffix), value); } protected void setArray(String settingSuffix, String... values) { putArray(localName(settingSuffix), values); } protected void setArray(String settingSuffix, DefaultIndexSettingsElement... values) { putArray(localName(settingSuffix), Arrays.stream(values).map(DefaultIndexSettingsElement::getName).toArray(String[]::new)); } private void put(String setting, String value) { builder = builder.put(setting, value); } private void putArray(String setting, String... values) { builder = builder.putArray(setting, values); } private String localName(String settingSuffix) { return ANALYSIS + DELIMITER + type + DELIMITER + name + DELIMITER + settingSuffix; } public Settings settings() { return builder.build(); } protected abstract void setup(); public SortedMap<String, String> fieldMapping() { throw new UnsupportedOperationException("The elasticsearch configuration element '" + name + "' cannot be used as field mapping."); } public String subField(String fieldName) { return fieldName + SUB_FIELD_DELIMITER + getSubFieldSuffix(); } public String getSubFieldSuffix() { return getName(); } public String getName() { return name; } }