This is an automated email from the ASF dual-hosted git repository.

zehnder pushed a commit to branch 
3282-dd-regex-based-preprocessing-rule-to-adapters
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit ffd5e7cc000640961e5617e05fe2ee656a20ac24
Author: Philipp Zehnder <[email protected]>
AuthorDate: Fri Oct 4 18:10:11 2024 +0200

    feat(#3282): Add new rule and rule description for regex rule
---
 .../convert/ToOriginalSchemaConverter.java         |  6 ++
 .../convert/ToTransformedSchemaConverter.java      | 12 +++
 ...StatefulTransformationRuleGeneratorVisitor.java |  6 ++
 ...tatelessTransformationRuleGeneratorVisitor.java | 11 +++
 .../transform/value/RegexTransformationRule.java   | 70 ++++++++++++++++
 .../shared/preprocessing/convert/Helpers.java      | 31 +++++--
 .../convert/ToOriginalSchemaConverterTest.java     | 20 ++---
 .../convert/ToTransformedSchemaConverterTest.java  | 75 ++++++++++++-----
 .../value/RegexTransformationRuleTest.java         | 96 ++++++++++++++++++++++
 .../connect/rules/ITransformationRuleVisitor.java  |  3 +
 .../connect/rules/TransformationRulePriority.java  |  1 +
 .../value/RegexTransformationRuleDescription.java  | 75 +++++++++++++++++
 .../value/ValueTransformationRuleDescription.java  |  1 +
 13 files changed, 372 insertions(+), 35 deletions(-)

diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
index 8e2381d506..100029741a 100644
--- 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverter.java
@@ -30,6 +30,7 @@ import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescript
 import 
org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 import org.apache.streampipes.model.schema.EventProperty;
@@ -90,6 +91,11 @@ public class ToOriginalSchemaConverter implements 
ITransformationRuleVisitor, Pr
     property.setRuntimeName(rule.getOldRuntimeKey());
   }
 
+  @Override
+  public void visit(RegexTransformationRuleDescription rule) {
+    // does not affect schema
+  }
+
   @Override
   public void visit(EventRateTransformationRuleDescription rule) {
     // does not affect schema
diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
index 8ea159406f..00dcd7cc43 100644
--- 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverter.java
@@ -31,6 +31,7 @@ import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescript
 import 
org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 import org.apache.streampipes.model.schema.EventProperty;
@@ -95,6 +96,7 @@ public class ToTransformedSchemaConverter implements 
ITransformationRuleVisitor,
     property.setRuntimeName(rule.getNewRuntimeKey());
   }
 
+
   @Override
   public void visit(EventRateTransformationRuleDescription rule) {
     // does not affect schema
@@ -149,6 +151,16 @@ public class ToTransformedSchemaConverter implements 
ITransformationRuleVisitor,
     metadata.put("correctionValue", rule.getCorrectionValue());
   }
 
+  @Override
+  public void visit(RegexTransformationRuleDescription rule) {
+    var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
+    var metadata = property.getAdditionalMetadata();
+
+    metadata.put("regex", rule.getRegex());
+    metadata.put("replaceWith", rule.getReplaceWith());
+    metadata.put("replaceAll", rule.isReplaceAll());
+  }
+
   @Override
   public void visit(TimestampTranfsformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatefulTransformationRuleGeneratorVisitor.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatefulTransformationRuleGeneratorVisitor.java
index c8e3c4cb5d..b1d9c0956c 100644
--- 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatefulTransformationRuleGeneratorVisitor.java
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatefulTransformationRuleGeneratorVisitor.java
@@ -30,6 +30,7 @@ import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescript
 import 
org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 
@@ -55,6 +56,11 @@ public class StatefulTransformationRuleGeneratorVisitor 
extends TransformationRu
     // skip (not a stateful transformation)
   }
 
+  @Override
+  public void visit(RegexTransformationRuleDescription rule) {
+    // skip (not a stateful transformation)
+  }
+
   @Override
   public void visit(EventRateTransformationRuleDescription ruleDesc) {
     rules.add(
diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatelessTransformationRuleGeneratorVisitor.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatelessTransformationRuleGeneratorVisitor.java
index 1728d8db27..1ca7d68dbd 100644
--- 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatelessTransformationRuleGeneratorVisitor.java
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/generator/StatelessTransformationRuleGeneratorVisitor.java
@@ -26,6 +26,7 @@ import 
org.apache.streampipes.connect.shared.preprocessing.transform.schema.Rena
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.AddTimestampTransformationRule;
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.CorrectionValueTransformationRule;
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.DatatypeTransformationRule;
+import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.RegexTransformationRule;
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.TimestampTranformationRuleMode;
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.TimestampTransformationRule;
 import 
org.apache.streampipes.connect.shared.preprocessing.transform.value.UnitTransformationRule;
@@ -40,6 +41,7 @@ import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescript
 import 
org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 
@@ -71,6 +73,15 @@ public class StatelessTransformationRuleGeneratorVisitor 
extends TransformationR
         Utils.getLastKey(ruleDesc.getNewRuntimeKey())));
   }
 
+  @Override
+  public void visit(RegexTransformationRuleDescription rule) {
+    rules.add(new RegexTransformationRule(
+        Utils.toKeyArray(rule.getRuntimeKey()),
+        rule.getRegex(),
+        rule.getReplaceWith(),
+        rule.isReplaceAll()));
+  }
+
   @Override
   public void visit(EventRateTransformationRuleDescription ruleDesc) {
     // Do nothing
diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRule.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRule.java
new file mode 100644
index 0000000000..83c27c9068
--- /dev/null
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRule.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.shared.preprocessing.transform.value;
+
+import 
org.apache.streampipes.connect.shared.preprocessing.SupportsNestedTransformationRule;
+
+import java.util.List;
+import java.util.Map;
+
+public class RegexTransformationRule extends SupportsNestedTransformationRule {
+
+  private final List<String> eventKeys;
+  private final String regex;
+  private final String replaceWith;
+  private final boolean replaceAll;
+
+  public RegexTransformationRule(
+      List<String> eventKeys,
+      String regex,
+      String replaceWith,
+      boolean replaceAll
+  ) {
+    this.eventKeys = eventKeys;
+    this.regex = regex;
+    this.replaceWith = replaceWith;
+    this.replaceAll = replaceAll;
+  }
+
+  @Override
+  protected List<String> getEventKeys() {
+    return eventKeys;
+  }
+
+  @Override
+  protected void applyTransformation(Map<String, Object> event, List<String> 
eventKey) {
+    var oldValue = event.get(eventKey.get(0));
+
+    var newValue = "";
+
+    if (oldValue instanceof String oldStringValue) {
+
+      if (this.replaceAll) {
+        newValue = oldStringValue.replaceAll(regex, this.replaceWith);
+      } else {
+        newValue = oldStringValue.replaceFirst(regex, this.replaceWith);
+      }
+
+      event.put(eventKey.get(0), newValue);
+    } else {
+      // add empty string if key is not present or wrong data type
+      event.put(eventKey.get(0), newValue);
+    }
+  }
+}
diff --git 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/Helpers.java
 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/Helpers.java
index ca8dd0c347..a8e823a520 100644
--- 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/Helpers.java
+++ 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/Helpers.java
@@ -21,6 +21,7 @@ package 
org.apache.streampipes.connect.shared.preprocessing.convert;
 import org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription;
 import org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription;
 import org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyNested;
@@ -34,7 +35,8 @@ import java.util.List;
 public class Helpers {
 
   public static String getUnit(EventProperty eventProperty) {
-    return ((EventPropertyPrimitive) 
eventProperty).getMeasurementUnit().toString();
+    return ((EventPropertyPrimitive) eventProperty).getMeasurementUnit()
+                                                   .toString();
   }
 
   public static List<EventProperty> makeSimpleProperties(boolean addTimestamp) 
{
@@ -67,16 +69,35 @@ public class Helpers {
     return rule;
   }
 
-  public static MoveRuleDescription makeMoveTransformationRule(String 
runtimeKey,
-                                                         String newRuntimeKey) 
{
+  public static RegexTransformationRuleDescription makeRegexTransformationRule(
+      String runtimeKey,
+      String regex,
+      String replaceWith,
+      boolean replaceAll
+  ) {
+    var rule = new RegexTransformationRuleDescription();
+    rule.setRuntimeKey(runtimeKey);
+    rule.setRegex(regex);
+    rule.setReplaceWith(replaceWith);
+    rule.setReplaceAll(replaceAll);
+
+    return rule;
+  }
+
+  public static MoveRuleDescription makeMoveTransformationRule(
+      String runtimeKey,
+      String newRuntimeKey
+  ) {
     var rule = new MoveRuleDescription();
     rule.setOldRuntimeKey(runtimeKey);
     rule.setNewRuntimeKey(newRuntimeKey);
     return rule;
   }
 
-  public static RenameRuleDescription makeRenameTransformationRule(String 
runtimeKey,
-                                                             String 
newRuntimeName) {
+  public static RenameRuleDescription makeRenameTransformationRule(
+      String runtimeKey,
+      String newRuntimeName
+  ) {
     var rule = new RenameRuleDescription();
     rule.setOldRuntimeKey(runtimeKey);
     rule.setNewRuntimeKey(newRuntimeName);
diff --git 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverterTest.java
 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverterTest.java
index 966ea56c84..e5f1e1ed3d 100644
--- 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverterTest.java
+++ 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToOriginalSchemaConverterTest.java
@@ -25,7 +25,6 @@ import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.sdk.helpers.EpProperties;
 import org.apache.streampipes.sdk.helpers.Labels;
 
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -37,6 +36,7 @@ import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helper
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeNestedProperties;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeSimpleProperties;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeUnitTransformationRule;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class ToOriginalSchemaConverterTest {
 
@@ -52,8 +52,8 @@ public class ToOriginalSchemaConverterTest {
 
     var resultProperties = executeAndReturnResult(properties, rules);
 
-    Assertions.assertEquals(3, resultProperties.size());
-    Assertions.assertEquals("originalUnit", getUnit(resultProperties.get(0)));
+    assertEquals(3, resultProperties.size());
+    assertEquals("originalUnit", getUnit(resultProperties.get(0)));
   }
 
   @Test
@@ -68,8 +68,8 @@ public class ToOriginalSchemaConverterTest {
     var nestedResultProperty = ((EventPropertyNested) 
resultProperties.get(1)).getEventProperties()
                                                                               
.get(0);
 
-    Assertions.assertEquals(2, resultProperties.size());
-    Assertions.assertEquals("originalUnit", getUnit(nestedResultProperty));
+    assertEquals(2, resultProperties.size());
+    assertEquals("originalUnit", getUnit(nestedResultProperty));
   }
 
   @Test
@@ -84,13 +84,13 @@ public class ToOriginalSchemaConverterTest {
     rules.add(makeMoveTransformationRule("epToBeMoved", "nested"));
 
     var result = executeAndReturnResult(properties, rules);
-    Assertions.assertEquals(3, result.size());
-    Assertions.assertEquals(
+    assertEquals(3, result.size());
+    assertEquals(
         "timestamp",
         result.get(0)
               .getRuntimeName()
     );
-    Assertions.assertEquals(
+    assertEquals(
         2,
         ((EventPropertyNested) result.get(1)).getEventProperties()
                                              .size()
@@ -104,8 +104,8 @@ public class ToOriginalSchemaConverterTest {
 
     rules.add(makeDeleteTransformationRule("epToBeRestored"));
     var result = executeAndReturnResult(properties, rules);
-    Assertions.assertEquals(4, result.size());
-    Assertions.assertEquals(
+    assertEquals(4, result.size());
+    assertEquals(
         "epToBeRestored",
         result.get(3)
               .getRuntimeName()
diff --git 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverterTest.java
 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverterTest.java
index 44443d151a..ab753dad24 100644
--- 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverterTest.java
+++ 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/convert/ToTransformedSchemaConverterTest.java
@@ -25,7 +25,6 @@ import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.sdk.helpers.EpProperties;
 import org.apache.streampipes.sdk.helpers.Labels;
 
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -35,9 +34,12 @@ import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helper
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeDeleteTransformationRule;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeMoveTransformationRule;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeNestedProperties;
+import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeRegexTransformationRule;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeRenameTransformationRule;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeSimpleProperties;
 import static 
org.apache.streampipes.connect.shared.preprocessing.convert.Helpers.makeUnitTransformationRule;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class ToTransformedSchemaConverterTest {
 
@@ -51,8 +53,27 @@ public class ToTransformedSchemaConverterTest {
 
     var resultProperties = executeAndReturnResult(properties, rules);
 
-    Assertions.assertEquals(3, resultProperties.size());
-    Assertions.assertEquals("targetUnit", getUnit(resultProperties.get(0)));
+    assertEquals(3, resultProperties.size());
+    assertEquals("targetUnit", getUnit(resultProperties.get(0)));
+  }
+
+
+  @Test
+  public void testRegexTransformationRule() {
+    List<EventProperty> properties = makeSimpleProperties(true);
+
+    var rules = new ArrayList<TransformationRuleDescription>();
+
+    rules.add(makeRegexTransformationRule("stringProp", ",", "", true));
+
+    var resultProperties = executeAndReturnResult(properties, rules);
+
+    assertEquals(3, resultProperties.size());
+
+    assertEquals(3, resultProperties.get(0).getAdditionalMetadata().size());
+    
assertTrue(resultProperties.get(0).getAdditionalMetadata().containsKey("regex"));
+    
assertTrue(resultProperties.get(0).getAdditionalMetadata().containsKey("replaceWith"));
+    
assertTrue(resultProperties.get(0).getAdditionalMetadata().containsKey("replaceAll"));
   }
 
 
@@ -64,9 +85,12 @@ public class ToTransformedSchemaConverterTest {
     rules.add(makeRenameTransformationRule("stringProp", "newStringProp"));
 
     var result = executeAndReturnResult(properties, rules);
-    Assertions.assertEquals(3, result.size());
-    Assertions.assertEquals("newStringProp",
-                            result.get(0).getRuntimeName());
+    assertEquals(3, result.size());
+    assertEquals(
+        "newStringProp",
+        result.get(0)
+              .getRuntimeName()
+    );
   }
 
   @Test
@@ -77,9 +101,12 @@ public class ToTransformedSchemaConverterTest {
     rules.add(makeDeleteTransformationRule("stringProp"));
 
     var result = executeAndReturnResult(properties, rules);
-    Assertions.assertEquals(2, result.size());
-    Assertions.assertEquals("intProp",
-                            result.get(0).getRuntimeName());
+    assertEquals(2, result.size());
+    assertEquals(
+        "intProp",
+        result.get(0)
+              .getRuntimeName()
+    );
   }
 
   @Test
@@ -92,11 +119,17 @@ public class ToTransformedSchemaConverterTest {
     rules.add(makeMoveTransformationRule("epToBeMoved", "nested"));
 
     var result = executeAndReturnResult(properties, rules);
-    Assertions.assertEquals(2, result.size());
-    Assertions.assertEquals("timestamp",
-                            result.get(0).getRuntimeName());
-    Assertions.assertEquals(3,
-                            ((EventPropertyNested) 
result.get(1)).getEventProperties().size());
+    assertEquals(2, result.size());
+    assertEquals(
+        "timestamp",
+        result.get(0)
+              .getRuntimeName()
+    );
+    assertEquals(
+        3,
+        ((EventPropertyNested) result.get(1)).getEventProperties()
+                                             .size()
+    );
   }
 
   @Test
@@ -108,18 +141,20 @@ public class ToTransformedSchemaConverterTest {
     rules.add(makeUnitTransformationRule("nested<-=>stringProp"));
 
     var resultProperties = executeAndReturnResult(properties, rules);
-    var nestedResultProperty = ((EventPropertyNested) 
resultProperties.get(1)).getEventProperties().get(0);
+    var nestedResultProperty = ((EventPropertyNested) 
resultProperties.get(1)).getEventProperties()
+                                                                              
.get(0);
 
-    Assertions.assertEquals(2, resultProperties.size());
-    Assertions.assertEquals("targetUnit", getUnit(nestedResultProperty));
+    assertEquals(2, resultProperties.size());
+    assertEquals("targetUnit", getUnit(nestedResultProperty));
   }
 
-  private List<EventProperty> executeAndReturnResult(List<EventProperty> 
properties,
-                                                     
List<TransformationRuleDescription> rules) {
+  private List<EventProperty> executeAndReturnResult(
+      List<EventProperty> properties,
+      List<TransformationRuleDescription> rules
+  ) {
     var result = new SchemaConverter().toTransformedSchema(new 
EventSchema(properties), rules);
     return result.getEventProperties();
   }
 
 
-
 }
diff --git 
a/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRuleTest.java
 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRuleTest.java
new file mode 100644
index 0000000000..be7cb23a8d
--- /dev/null
+++ 
b/streampipes-connect-shared/src/test/java/org/apache/streampipes/connect/shared/preprocessing/transform/value/RegexTransformationRuleTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.shared.preprocessing.transform.value;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RegexTransformationRuleTest {
+  private static final String PROPERTY = "property";
+
+  private Map<String, Object> event;
+
+  @BeforeEach
+  public void setUp() {
+    event = new HashMap<>();
+  }
+
+  @Test
+  void applyTransformation_ReplaceAllComma() {
+    event.put(PROPERTY, "a,b,");
+    var rule = getRegexTransformationRule(",", "", true);
+
+    rule.apply(event);
+
+    assertEquals("ab", event.get(PROPERTY));
+  }
+
+  @Test
+  void applyTransformation_ReplaceOneComma() {
+    event.put(PROPERTY, "a,b,");
+    var rule = getRegexTransformationRule(",", "", false);
+
+    rule.apply(event);
+
+    assertEquals("ab,", event.get(PROPERTY));
+  }
+
+  @Test
+  void applyTransformation_NoReplacement() {
+    event.put(PROPERTY, "ab");
+    var rule = getRegexTransformationRule(",", "", false);
+
+    rule.apply(event);
+
+    assertEquals("ab", event.get(PROPERTY));
+  }
+
+  @Test
+  void applyTransformation_WrongDataType() {
+    event.put(PROPERTY, 5);
+    var rule = getRegexTransformationRule(",", "", false);
+
+    rule.apply(event);
+
+    assertEquals("", event.get(PROPERTY));
+  }
+
+  @Test
+  void applyTransformation_ValueNotPresent() {
+    var rule = getRegexTransformationRule(",", "", false);
+
+    rule.apply(event);
+
+    assertEquals("", event.get(PROPERTY));
+  }
+
+  private RegexTransformationRule getRegexTransformationRule(
+      String regex,
+      String replaceWith,
+      boolean replaceAll
+  ) {
+    return new RegexTransformationRule(List.of(PROPERTY), regex, replaceWith, 
replaceAll);
+  }
+}
\ No newline at end of file
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/ITransformationRuleVisitor.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/ITransformationRuleVisitor.java
index bb45ff0eaf..78dbd37da1 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/ITransformationRuleVisitor.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/ITransformationRuleVisitor.java
@@ -28,6 +28,7 @@ import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescript
 import 
org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription;
 import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
 
@@ -41,6 +42,8 @@ public interface ITransformationRuleVisitor {
 
   void visit(RenameRuleDescription rule);
 
+  void visit(RegexTransformationRuleDescription rule);
+
   void visit(EventRateTransformationRuleDescription rule);
 
   void visit(RemoveDuplicatesTransformationRuleDescription rule);
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
index 3fcb8ba429..28458d81c8 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
@@ -31,6 +31,7 @@ public enum TransformationRulePriority {
   CHANGE_UNIT(310),
   TIMESTAMP_TRANSFORMATION(320),
   CORRECTION_VALUE(330),
+  REGEX_TRANSFORMATION(331),
   CHANGE_DATATYPE(340),
 
   REMOVE_DUPLICATES(410),
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/RegexTransformationRuleDescription.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/RegexTransformationRuleDescription.java
new file mode 100644
index 0000000000..7dd9eed5c2
--- /dev/null
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/RegexTransformationRuleDescription.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.rules.value;
+
+import org.apache.streampipes.model.connect.rules.ITransformationRuleVisitor;
+import org.apache.streampipes.model.connect.rules.TransformationRulePriority;
+
+public class RegexTransformationRuleDescription extends 
ValueTransformationRuleDescription {
+
+  private String runtimeKey;
+  private String regex;
+  private String replaceWith;
+  private boolean replaceAll;
+
+  public RegexTransformationRuleDescription() {
+  }
+
+  @Override
+  public void accept(ITransformationRuleVisitor visitor) {
+    visitor.visit(this);
+  }
+
+  @Override
+  public int getRulePriority() {
+    return TransformationRulePriority.REGEX_TRANSFORMATION.getCode();
+  }
+
+  public String getRuntimeKey() {
+    return runtimeKey;
+  }
+
+  public void setRuntimeKey(String runtimeKey) {
+    this.runtimeKey = runtimeKey;
+  }
+
+  public String getRegex() {
+    return regex;
+  }
+
+  public void setRegex(String regex) {
+    this.regex = regex;
+  }
+
+  public String getReplaceWith() {
+    return replaceWith;
+  }
+
+  public void setReplaceWith(String replaceWith) {
+    this.replaceWith = replaceWith;
+  }
+
+  public boolean isReplaceAll() {
+    return replaceAll;
+  }
+
+  public void setReplaceAll(boolean replaceAll) {
+    this.replaceAll = replaceAll;
+  }
+}
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ValueTransformationRuleDescription.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ValueTransformationRuleDescription.java
index dee07a2151..e1f6e495bb 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ValueTransformationRuleDescription.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/value/ValueTransformationRuleDescription.java
@@ -28,6 +28,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
     @JsonSubTypes.Type(TimestampTranfsformationRuleDescription.class),
     @JsonSubTypes.Type(UnitTransformRuleDescription.class),
     @JsonSubTypes.Type(CorrectionValueTransformationRuleDescription.class),
+    @JsonSubTypes.Type(RegexTransformationRuleDescription.class),
 })
 public abstract class ValueTransformationRuleDescription extends 
TransformationRuleDescription {
 

Reply via email to