]> git.basschouten.com Git - openhab-addons.git/blob
f97394b00d22ab0ba04e78dc27e58c53d276a512
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.transform.map.internal;
14
15 import java.io.IOException;
16 import java.io.StringReader;
17 import java.net.URI;
18 import java.util.Collection;
19 import java.util.Locale;
20 import java.util.Map;
21 import java.util.Properties;
22 import java.util.Set;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.stream.Collectors;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.core.common.registry.RegistryChangeListener;
29 import org.openhab.core.config.core.ConfigOptionProvider;
30 import org.openhab.core.config.core.ParameterOption;
31 import org.openhab.core.transform.TransformationConfiguration;
32 import org.openhab.core.transform.TransformationConfigurationRegistry;
33 import org.openhab.core.transform.TransformationException;
34 import org.openhab.core.transform.TransformationService;
35 import org.osgi.service.component.annotations.Activate;
36 import org.osgi.service.component.annotations.Component;
37 import org.osgi.service.component.annotations.Deactivate;
38 import org.osgi.service.component.annotations.Reference;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * <p>
44  * The implementation of {@link TransformationService} which simply maps strings to other strings
45  *
46  * @author Kai Kreuzer - Initial contribution and API
47  * @author GaĆ«l L'hopital - Make it localizable
48  * @author Jan N. Klug - Refactored to use {@link TransformationConfigurationRegistry}
49  */
50 @NonNullByDefault
51 @Component(service = { TransformationService.class, ConfigOptionProvider.class }, property = {
52         "openhab.transform=MAP" })
53 public class MapTransformationService
54         implements TransformationService, ConfigOptionProvider, RegistryChangeListener<TransformationConfiguration> {
55     private final Logger logger = LoggerFactory.getLogger(MapTransformationService.class);
56
57     private static final String PROFILE_CONFIG_URI = "profile:transform:MAP";
58     private static final String CONFIG_PARAM_FUNCTION = "function";
59     private static final Set<String> SUPPORTED_CONFIGURATION_TYPES = Set.of("map");
60
61     private final TransformationConfigurationRegistry transformationConfigurationRegistry;
62     private final Map<String, Properties> cachedTransformations = new ConcurrentHashMap<>();
63
64     @Activate
65     public MapTransformationService(
66             @Reference TransformationConfigurationRegistry transformationConfigurationRegistry) {
67         this.transformationConfigurationRegistry = transformationConfigurationRegistry;
68         transformationConfigurationRegistry.addRegistryChangeListener(this);
69     }
70
71     @Deactivate
72     public void deactivate() {
73         transformationConfigurationRegistry.removeRegistryChangeListener(this);
74     }
75
76     @Override
77     public @Nullable String transform(String function, String source) throws TransformationException {
78         // always get a configuration from the registry to account for changed system locale
79         TransformationConfiguration transformationConfiguration = transformationConfigurationRegistry.get(function,
80                 null);
81
82         if (transformationConfiguration != null) {
83             if (!cachedTransformations.containsKey(transformationConfiguration.getUID())) {
84                 importConfiguration(transformationConfiguration);
85             }
86             Properties properties = cachedTransformations.get(function);
87             if (properties != null) {
88                 String target = properties.getProperty(source);
89
90                 if (target == null) {
91                     target = properties.getProperty("");
92                     if (target == null) {
93                         throw new TransformationException("Target value not found in map for '" + source + "'");
94                     }
95                 }
96
97                 logger.debug("Transformation resulted in '{}'", target);
98                 return target;
99             }
100         }
101         throw new TransformationException("Could not find configuration '" + function + "' or failed to parse it.");
102     }
103
104     @Override
105     public @Nullable Collection<ParameterOption> getParameterOptions(URI uri, String param, @Nullable String context,
106             @Nullable Locale locale) {
107         if (PROFILE_CONFIG_URI.equals(uri.toString())) {
108             if (CONFIG_PARAM_FUNCTION.equals(param)) {
109                 return transformationConfigurationRegistry.getConfigurations(SUPPORTED_CONFIGURATION_TYPES).stream()
110                         .map(c -> new ParameterOption(c.getUID(), c.getLabel())).collect(Collectors.toList());
111             }
112         }
113         return null;
114     }
115
116     @Override
117     public void added(TransformationConfiguration element) {
118         // do nothing, configurations are added to cache if needed
119     }
120
121     @Override
122     public void removed(TransformationConfiguration element) {
123         cachedTransformations.remove(element.getUID());
124     }
125
126     @Override
127     public void updated(TransformationConfiguration oldElement, TransformationConfiguration element) {
128         if (cachedTransformations.remove(oldElement.getUID()) != null) {
129             // import only if it was present before
130             importConfiguration(element);
131         }
132     }
133
134     private void importConfiguration(@Nullable TransformationConfiguration configuration) {
135         if (configuration != null) {
136             try {
137                 Properties properties = new Properties();
138                 properties.load(new StringReader(configuration.getContent()));
139                 cachedTransformations.put(configuration.getUID(), properties);
140             } catch (IOException ignored) {
141             }
142         }
143     }
144 }