/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.elasticsearch.settings.impl.translation; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.lucene.analysis.util.AbstractAnalysisFactory; import org.hibernate.search.elasticsearch.settings.impl.model.AnalysisDefinition; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; /** * A utility that helps {@link DefaultElasticsearchAnalyzerDefinitionTranslator} build its translation maps. * * @author Yoann Rodiere */ class LuceneAnalysisDefinitionTranslationMapBuilder<D extends AnalysisDefinition> { private final Class<D> targetClass; private final Map<String, AnalysisDefinitionFactory<D>> result = new HashMap<>(); public LuceneAnalysisDefinitionTranslationMapBuilder(Class<D> targetClass) { this.targetClass = targetClass; } public SimpleAnalysisDefinitionFactoryBuilder<D> builder(Class<? extends AbstractAnalysisFactory> luceneClass, String typeName) { return new SimpleAnalysisDefinitionFactoryBuilder<>( this, luceneClass, typeName ); } public LuceneAnalysisDefinitionTranslationMapBuilder<D> add(Class<? extends AbstractAnalysisFactory> luceneClass, AnalysisDefinitionFactory<D> definitionFactory) { result.put( luceneClass.getName(), definitionFactory ); return this; } public LuceneAnalysisDefinitionTranslationMapBuilder<D> addJsonPassThrough(Class<? extends AbstractAnalysisFactory> factoryClass) { result.put( factoryClass.getName(), new JsonPassThroughAnalysisDefinitionFactory<>( targetClass, factoryClass ) ); return this; } public Map<String, AnalysisDefinitionFactory<D>> build() { return Collections.unmodifiableMap( result ); } static class SimpleAnalysisDefinitionFactoryBuilder<D extends AnalysisDefinition> { private final LuceneAnalysisDefinitionTranslationMapBuilder<D> parent; private final Class<? extends AbstractAnalysisFactory> luceneClass; private final String typeName; private List<ParametersTransformer> parametersTransformers = new ArrayList<>(); private Map<String, String> parameterNameTranslations; private Map<String, ParameterValueTransformer> parameterValueTranslations; private Map<String, JsonElement> staticParameters; private SimpleAnalysisDefinitionFactoryBuilder(LuceneAnalysisDefinitionTranslationMapBuilder<D> parent, Class<? extends AbstractAnalysisFactory> luceneClass, String typeName) { super(); this.parent = parent; this.luceneClass = luceneClass; this.typeName = typeName; } public SimpleAnalysisDefinitionFactoryBuilder<D> transform(ParametersTransformer transformer) { parametersTransformers.add( transformer ); return this; } public SimpleAnalysisDefinitionFactoryBuilder<D> add(String elasticsearchParam, String value) { if ( staticParameters == null ) { staticParameters = new LinkedHashMap<>(); } staticParameters.put( elasticsearchParam, new JsonPrimitive( value ) ); return this; } public SimpleAnalysisDefinitionFactoryBuilder<D> disallow(String luceneParam) { return transform( luceneParam, new ThrowingUnsupportedParameterValueTransformer( luceneClass, luceneParam ) ); } public SimpleAnalysisDefinitionFactoryBuilder<D> mandateAndStrip(String luceneParam, String luceneValue) { return transform( new ThrowingMandatoryStrippedParametersTransformer( luceneClass, luceneParam, luceneValue ) ); } public SimpleAnalysisDefinitionFactoryBuilder<D> rename(String luceneParam, String elasticsearchParam) { if ( parameterNameTranslations == null ) { parameterNameTranslations = new HashMap<>(); } parameterNameTranslations.put( luceneParam, elasticsearchParam ); return this; } public MapParameterValueTransformerBuilder<D> transform(String luceneParam) { return new MapParameterValueTransformerBuilder<>( this, luceneClass, luceneParam ); } public SimpleAnalysisDefinitionFactoryBuilder<D> transform(String luceneParam, ParameterValueTransformer transformer) { if ( parameterValueTranslations == null ) { parameterValueTranslations = new HashMap<>(); } parameterValueTranslations.put( luceneParam, transformer ); return this; } public LuceneAnalysisDefinitionTranslationMapBuilder<D> end() { if ( staticParameters != null ) { /* * Add static parameters first, so that they can be overridden by * both custom transformers and the simple transformer added just below. */ parametersTransformers.add( 0, new StaticParametersTransformer( staticParameters ) ); } if ( parameterNameTranslations == null ) { parameterNameTranslations = Collections.emptyMap(); } if ( parameterValueTranslations == null ) { parameterValueTranslations = Collections.emptyMap(); } /* * This transformer will only handle those parameters that were not consumed by * custom transformer, so we can safely execute it last. * * We always add this transformer, even when the maps we pass to the constructor are empty, * because it also handles unknown parameters. */ parametersTransformers.add( new SimpleParametersTransformer( parameterNameTranslations, parameterValueTranslations ) ); return parent.add( luceneClass, new SimpleAnalysisDefinitionFactory<>( parent.targetClass, typeName, parametersTransformers ) ); } } static class MapParameterValueTransformerBuilder<D extends AnalysisDefinition> { private final SimpleAnalysisDefinitionFactoryBuilder<D> parent; private final Class<?> factoryClass; private final String parameterName; private final Map<String, JsonElement> translations = new HashMap<>(); private MapParameterValueTransformerBuilder(SimpleAnalysisDefinitionFactoryBuilder<D> parent, Class<?> factoryClass, String parameterName) { super(); this.parent = parent; this.factoryClass = factoryClass; this.parameterName = parameterName; } public MapParameterValueTransformerBuilder<D> add(String luceneValue, String elasticsearchValue) { return add( luceneValue, new JsonPrimitive( elasticsearchValue ) ); } public MapParameterValueTransformerBuilder<D> add(String luceneValue, JsonElement elasticsearchValue) { translations.put( luceneValue, elasticsearchValue ); return this; } public SimpleAnalysisDefinitionFactoryBuilder<D> end() { return parent.transform( parameterName, new MapParameterValueTransformer( factoryClass, parameterName, translations ) ); } } }