Add isTransform(), isEmpty() and isPresent() to ChannelTransformation (#4355)

* Add isEmpty() and isPresent() to ChannelTransformation
* Add isValidTransformation helper method

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
jimtng 2024-08-31 02:47:55 +10:00 committed by GitHub
parent 66d55f77b5
commit 8a59844451
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 94 additions and 2 deletions

View File

@ -71,18 +71,67 @@ public class ChannelTransformation {
return Arrays.stream(transformationString.split("")).filter(s -> !s.isBlank());
}
/**
* Checks whether this object contains no transformation steps.
*
* @return <code>true</code> if the transformation is empty, <code>false</code> otherwise.
*/
public boolean isEmpty() {
return transformationSteps.isEmpty();
}
/**
* Checks whether this object contains at least one transformation step.
*
* @return <code>true</code> if the transformation is present, <code>false</code> otherwise.
*/
public boolean isPresent() {
return !isEmpty();
}
/**
* Applies all transformations to the given value.
*
* @param value the value to transform.
* @return the transformed value or an empty optional if the transformation failed.
* If the transformation is empty, the original value is returned.
*/
public Optional<String> apply(String value) {
Optional<String> valueOptional = Optional.of(value);
// process all transformations
for (TransformationStep transformationStep : transformationSteps) {
valueOptional = valueOptional.flatMap(transformationStep::apply);
valueOptional = valueOptional.flatMap(v -> {
Optional<String> result = transformationStep.apply(v);
if (logger.isTraceEnabled()) {
logger.trace("Transformed '{}' to '{}' using '{}'", v, result.orElse(null), transformationStep);
}
return result;
});
}
logger.trace("Transformed '{}' to '{}' using '{}'", value, valueOptional, transformationSteps);
return valueOptional;
}
/**
* Checks whether the given string contains valid transformations.
*
* Valid single and chained transformations will return true.
*
* @param value the transformation string to check.
* @return <code>true</code> if the string contains valid transformations, <code>false</code> otherwise.
*/
public static boolean isValidTransformation(@Nullable String value) {
if (value == null || value.isBlank()) {
return false;
}
try {
return splitTransformationString(value).map(TransformationStep::new).count() > 0;
} catch (IllegalArgumentException e) {
return false;
}
}
private static class TransformationStep {
private static final List<Pattern> TRANSFORMATION_PATTERNS = List.of( //
Pattern.compile("(?<service>[a-zA-Z0-9]+)\\s*\\((?<function>.*)\\)$"), //

View File

@ -13,6 +13,7 @@
package org.openhab.core.thing.binding.generic;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@ -306,4 +307,46 @@ public class ChannelTransformationTest {
assertEquals(T2_RESULT, result);
}
@Test
public void testIsValidTransform() {
// single with colon
assertTrue(ChannelTransformation.isValidTransformation("FOO:BAR"));
assertTrue(ChannelTransformation.isValidTransformation(" FOO : BAR "));
// single with parens
assertTrue(ChannelTransformation.isValidTransformation("FOO(BAR())"));
assertTrue(ChannelTransformation.isValidTransformation(" FOO ( BAR) )")); // deliberate extra closing parens
// chained with colon
assertTrue(ChannelTransformation.isValidTransformation("FOO:BAR∩BAZ:QUX"));
assertTrue(ChannelTransformation.isValidTransformation("FOO:BAR∩BAZ:QUX()"));
assertTrue(ChannelTransformation.isValidTransformation(" FOO : BAR ∩ BAZ : QUX() "));
// chained with parens
assertTrue(ChannelTransformation.isValidTransformation("FOO(BAR)∩BAZ(QUX)"));
assertTrue(ChannelTransformation.isValidTransformation("FOO(BAR)∩BAZ(QUX())"));
assertTrue(ChannelTransformation.isValidTransformation("FOO(BAR)∩BAZ(QUX))")); // deliberate extra parens
assertTrue(ChannelTransformation.isValidTransformation(" FOO ( BAR ) ∩ BAZ ( QUX )"));
assertTrue(ChannelTransformation.isValidTransformation(" FOO ( BAR ) ∩ BAZ ( QUX() )"));
// mixed chains
assertTrue(ChannelTransformation.isValidTransformation("FOO:BAR∩BAZ(QUX)"));
assertTrue(ChannelTransformation.isValidTransformation("FOO(BAR)∩BAZ:QUX"));
assertTrue(ChannelTransformation.isValidTransformation("FOO:BAR()∩BAZ(QUX())"));
assertTrue(ChannelTransformation.isValidTransformation(" FOO : BAR ∩ BAZ ( QUX ) "));
assertTrue(ChannelTransformation.isValidTransformation(" FOO ( BAR ) ∩ BAZ : QUX "));
// invalid syntaxes
assertFalse(ChannelTransformation.isValidTransformation(null));
assertFalse(ChannelTransformation.isValidTransformation(""));
assertFalse(ChannelTransformation.isValidTransformation(" "));
assertFalse(ChannelTransformation.isValidTransformation("FOOBAR"));
assertFalse(ChannelTransformation.isValidTransformation("(FOO)BAR"));
assertFalse(ChannelTransformation.isValidTransformation("FOO∩BAR"));
assertFalse(ChannelTransformation.isValidTransformation("FOO:BAR∩BAZ"));
assertFalse(ChannelTransformation.isValidTransformation("FOO(BAR)∩BAZ"));
assertFalse(ChannelTransformation.isValidTransformation("FOO∩BAZ:BAR"));
assertFalse(ChannelTransformation.isValidTransformation("FOO∩BAZ(BAR)"));
}
}