Support channel transformation chaining with a list (#4353)

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
jimtng 2024-08-19 02:36:36 +10:00 committed by GitHub
parent bb2a2d10dc
commit 506ccd4f4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 70 additions and 13 deletions

View File

@ -17,7 +17,9 @@ import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.transform.TransformationException;
import org.openhab.core.transform.TransformationHelper;
@ -33,6 +35,7 @@ import org.slf4j.LoggerFactory;
*
* @author Jan N. Klug - Initial contribution
*/
@NonNullByDefault
public class ChannelTransformation {
private final Logger logger = LoggerFactory.getLogger(ChannelTransformation.class);
private List<TransformationStep> transformationSteps;
@ -40,8 +43,8 @@ public class ChannelTransformation {
public ChannelTransformation(@Nullable String transformationString) {
if (transformationString != null) {
try {
transformationSteps = Arrays.stream(transformationString.split("")).filter(s -> !s.isBlank())
.map(TransformationStep::new).toList();
transformationSteps = splitTransformationString(transformationString).map(TransformationStep::new)
.toList();
return;
} catch (IllegalArgumentException e) {
logger.warn("Transformation ignored, failed to parse {}: {}", transformationString, e.getMessage());
@ -50,6 +53,24 @@ public class ChannelTransformation {
transformationSteps = List.of();
}
public ChannelTransformation(@Nullable List<String> transformationStrings) {
if (transformationStrings != null) {
try {
transformationSteps = transformationStrings.stream()
.flatMap(ChannelTransformation::splitTransformationString).map(TransformationStep::new)
.toList();
return;
} catch (IllegalArgumentException e) {
logger.warn("Transformation ignored, failed to parse {}: {}", transformationStrings, e.getMessage());
}
}
transformationSteps = List.of();
}
private static Stream<String> splitTransformationString(String transformationString) {
return Arrays.stream(transformationString.split("")).filter(s -> !s.isBlank());
}
public Optional<String> apply(String value) {
Optional<String> valueOptional = Optional.of(value);

View File

@ -17,6 +17,8 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -54,8 +56,8 @@ public class ChannelTransformationTest {
private static final String T3_NAME = T2_NAME;
private static final String T3_PATTERN = "a()b()))";
private static final String T3_INPUT = T2_INPUT;
private static final String T3_RESULT = T2_RESULT;
private static final String T3_INPUT = T2_RESULT;
private static final String T3_RESULT = "T3Result";
private @Mock @NonNullByDefault({}) TransformationService transformationService1Mock;
private @Mock @NonNullByDefault({}) TransformationService transformationService2Mock;
@ -163,6 +165,38 @@ public class ChannelTransformationTest {
assertEquals(T2_RESULT, result);
}
@Test
public void testTransformationsInAList() {
List<String> patterns = List.of(T1_NAME + ":" + T1_PATTERN, T2_NAME + ":" + T2_PATTERN);
ChannelTransformation transformation = new ChannelTransformation(patterns);
String result = transformation.apply(T1_INPUT).orElse(null);
assertEquals(T2_RESULT, result);
}
@Test
public void testMixedTransformationsInAList1() {
List<String> patterns = List.of(T1_NAME + ":" + T1_PATTERN + "" + T2_NAME + ":" + T2_PATTERN,
T3_NAME + ":" + T3_PATTERN);
ChannelTransformation transformation = new ChannelTransformation(patterns);
String result = transformation.apply(T1_INPUT).orElse(null);
assertEquals(T3_RESULT, result);
}
@Test
public void testMixedTransformationsInAList2() {
List<String> patterns = List.of(T1_NAME + ":" + T1_PATTERN,
T2_NAME + ":" + T2_PATTERN + "" + T3_NAME + ":" + T3_PATTERN);
ChannelTransformation transformation = new ChannelTransformation(patterns);
String result = transformation.apply(T1_INPUT).orElse(null);
assertEquals(T3_RESULT, result);
}
@Test
public void testParensDoubleTransformationWithoutSpaces() {
String pattern = T1_NAME + "(" + T1_PATTERN + ")∩" + T2_NAME + "(" + T2_PATTERN + ")";

View File

@ -62,7 +62,8 @@ public class ConverterTest {
@Test
public void numberItemConverter() {
NumberChannelHandler converter = new NumberChannelHandler(updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), new ChannelValueConverterConfig());
new ChannelTransformation((String) null), new ChannelTransformation((String) null),
new ChannelValueConverterConfig());
// without unit
Assertions.assertEquals(Optional.of(new DecimalType(1234)), converter.toState("1234"));
@ -80,7 +81,7 @@ public class ConverterTest {
ChannelValueConverterConfig channelConfig = new ChannelValueConverterConfig();
channelConfig.unit = "W";
NumberChannelHandler converter = new NumberChannelHandler(updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), channelConfig);
new ChannelTransformation((String) null), new ChannelTransformation((String) null), channelConfig);
// without unit
Assertions.assertEquals(Optional.of(new QuantityType<>(500, Units.WATT)), converter.toState("500"));
@ -117,7 +118,7 @@ public class ConverterTest {
ChannelHandlerContent content = new ChannelHandlerContent("PLAY".getBytes(StandardCharsets.UTF_8), "UTF-8",
null);
PlayerChannelHandler converter = new PlayerChannelHandler(updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), cfg);
new ChannelTransformation((String) null), new ChannelTransformation((String) null), cfg);
converter.process(content);
converter.process(content);
@ -132,7 +133,7 @@ public class ConverterTest {
ChannelHandlerContent content = new ChannelHandlerContent("123,34,47".getBytes(StandardCharsets.UTF_8), "UTF-8",
null);
ColorChannelHandler converter = new ColorChannelHandler(updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), cfg);
new ChannelTransformation((String) null), new ChannelTransformation((String) null), cfg);
converter.process(content);
Mockito.verify(updateStateMock).accept(HSBType.fromRGB(123, 34, 47));
@ -145,7 +146,7 @@ public class ConverterTest {
ChannelHandlerContent content = new ChannelHandlerContent("123,34,47".getBytes(StandardCharsets.UTF_8), "UTF-8",
null);
ColorChannelHandler converter = new ColorChannelHandler(updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), cfg);
new ChannelTransformation((String) null), new ChannelTransformation((String) null), cfg);
converter.process(content);
Mockito.verify(updateStateMock).accept(new HSBType("123,34,47"));
@ -155,7 +156,7 @@ public class ConverterTest {
public void rollerSHutterConverter() {
ChannelValueConverterConfig cfg = new ChannelValueConverterConfig();
RollershutterChannelHandler converter = new RollershutterChannelHandler(updateStateMock, postCommandMock,
sendValueMock, new ChannelTransformation(null), new ChannelTransformation(null), cfg);
sendValueMock, new ChannelTransformation((String) null), new ChannelTransformation((String) null), cfg);
// test 0 and 100
ChannelHandlerContent content = new ChannelHandlerContent("0".getBytes(StandardCharsets.UTF_8), "UTF-8", null);
@ -181,6 +182,7 @@ public class ConverterTest {
public GenericChannelHandler createConverter(Function<String, State> fcn) {
return new GenericChannelHandler(fcn, updateStateMock, postCommandMock, sendValueMock,
new ChannelTransformation(null), new ChannelTransformation(null), new ChannelValueConverterConfig());
new ChannelTransformation((String) null), new ChannelTransformation((String) null),
new ChannelValueConverterConfig());
}
}

View File

@ -59,10 +59,10 @@ public class AbstractTransformingItemConverterTest {
private @NonNullByDefault({}) AutoCloseable closeable;
@Spy
private ChannelTransformation stateChannelTransformation = new ChannelTransformation(null);
private ChannelTransformation stateChannelTransformation = new ChannelTransformation((String) null);
@Spy
private ChannelTransformation commandChannelTransformation = new ChannelTransformation(null);
private ChannelTransformation commandChannelTransformation = new ChannelTransformation((String) null);
@BeforeEach
public void init() {