2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.serial.internal.transform;
15 import java.lang.ref.WeakReference;
16 import java.util.Optional;
17 import java.util.function.Function;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.core.transform.TransformationException;
22 import org.openhab.core.transform.TransformationService;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * A transformation for a value used in {@link org.openhab.binding.serial.internal.channel.DeviceChannel}.
29 * @author David Graeff - Initial contribution
30 * @author Jan N. Klug - adapted from MQTT binding to HTTP binding
31 * @author Mike Major - Copied from HTTP binding to provide consistent user experience
34 public class SingleValueTransformation implements ValueTransformation {
35 private final Logger logger = LoggerFactory.getLogger(SingleValueTransformation.class);
36 private final Function<String, @Nullable TransformationService> transformationServiceSupplier;
37 private WeakReference<@Nullable TransformationService> transformationService = new WeakReference<>(null);
38 private final String pattern;
39 private final String serviceName;
42 * Creates a new channel state transformer.
44 * @param pattern A transformation pattern, starting with the transformation service
45 * name, followed by a colon and the transformation itself.
46 * @param transformationServiceSupplier
48 public SingleValueTransformation(final String pattern,
49 final Function<String, @Nullable TransformationService> transformationServiceSupplier) {
50 this.transformationServiceSupplier = transformationServiceSupplier;
51 final int index = pattern.indexOf(':');
53 throw new IllegalArgumentException(
54 "The transformation pattern must consist of the type and the pattern separated by a colon");
56 this.serviceName = pattern.substring(0, index).toUpperCase();
57 this.pattern = pattern.substring(index + 1);
61 public Optional<String> apply(final String value) {
62 TransformationService transformationService = this.transformationService.get();
63 if (transformationService == null) {
64 transformationService = transformationServiceSupplier.apply(serviceName);
65 if (transformationService == null) {
66 logger.warn("Transformation service {} for pattern {} not found!", serviceName, pattern);
67 return Optional.empty();
69 this.transformationService = new WeakReference<>(transformationService);
73 final String result = transformationService.transform(pattern, value);
75 logger.debug("Transformation {} returned empty result when applied to {}.", this, value);
76 return Optional.empty();
78 return Optional.of(result);
79 } catch (final TransformationException e) {
80 logger.warn("Executing transformation {} failed: {}", this, e.getMessage());
83 return Optional.empty();
87 public String toString() {
88 return "ChannelStateTransformation{pattern='" + pattern + "', serviceName='" + serviceName + "'}";