/* * Copyright (c) 2016 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available 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. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.align.custom; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.ResourceBundle; import java.util.function.Supplier; import javax.annotation.Nullable; import de.fhg.igd.slf4jplus.ALogger; import de.fhg.igd.slf4jplus.ALoggerFactory; import eu.esdihumboldt.hale.common.align.extension.function.FunctionDefinition; import eu.esdihumboldt.hale.common.align.extension.function.ParameterDefinition; import eu.esdihumboldt.hale.common.align.model.CellExplanation; import eu.esdihumboldt.hale.common.align.model.impl.mdexpl.MarkdownCellExplanation; import eu.esdihumboldt.hale.common.core.io.Text; import eu.esdihumboldt.hale.common.core.io.Value; import eu.esdihumboldt.hale.common.core.service.ServiceProvider; import groovy.text.Template; /** * Explanation for custom functions based on Markdown templates. * * @author Simon Templer */ public class DefaultCustomFunctionExplanation extends MarkdownCellExplanation implements CellExplanation { private static final ALogger log = ALoggerFactory .getLogger(DefaultCustomFunctionExplanation.class); private final Map<Locale, Value> templates; private Supplier<FunctionDefinition<?>> functionResolver; /** * Create an explanation with the given templates. * * @param templates map of localized templates * @param functionResolver the custom resolver for the associated function * definition, to be used instead of the usual mechanism to * resolve functions */ public DefaultCustomFunctionExplanation(Map<Locale, Value> templates, @Nullable Supplier<FunctionDefinition<?>> functionResolver) { super(); this.templates = templates; this.functionResolver = functionResolver; } /** * Create an explanation with the given templates. * * @param templates map of localized templates */ public DefaultCustomFunctionExplanation(Map<Locale, Value> templates) { this(templates, null); } @Override public Iterable<Locale> getSupportedLocales() { return Collections.unmodifiableSet(templates.keySet()); } /** * Copy constructor. * * @param other the explanation to copy */ public DefaultCustomFunctionExplanation(DefaultCustomFunctionExplanation other) { super(); if (other != null) { templates = new HashMap<>(other.templates); functionResolver = other.functionResolver; } else { templates = new HashMap<>(); functionResolver = null; } } /** * @param functionResolver the the custom resolver for the associated * function definition, to be used instead of the usual mechanism * to resolve functions */ public void setFunctionResolver(@Nullable Supplier<FunctionDefinition<?>> functionResolver) { this.functionResolver = functionResolver; } private Optional<Value> findTemplate(Locale locale) { ResourceBundle.Control control = ResourceBundle.Control .getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT); List<Locale> candidateLocales = control.getCandidateLocales("baseName", locale); for (Locale specificLocale : candidateLocales) { Value candidate = templates.get(specificLocale); if (candidate != null) { return Optional.of(candidate); } } return Optional.empty(); } @Override protected Optional<Template> loadTemplate(Class<?> clazz, Locale locale) { return findTemplate(locale).flatMap(template -> { try { Text text = template.as(Text.class); if (text != null) { return Optional.ofNullable(getEngine().createTemplate(text.getText())); } else { String str = template.as(String.class); if (str != null) { return Optional.ofNullable(getEngine().createTemplate(str)); } else { return Optional.empty(); } } } catch (Exception e) { log.error("Could not load cell explanation template", e); return Optional.empty(); } }); } @Override protected FunctionDefinition<? extends ParameterDefinition> loadFunction(String functionId, ServiceProvider provider) { if (functionResolver != null) { return functionResolver.get(); } return super.loadFunction(functionId, provider); } /** * @return the configured explanation templates (not modifiable) */ public Map<Locale, Value> getTemplates() { return Collections.unmodifiableMap(templates); } }