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

zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new f8a96ec002 feat(#3282): regex based preprocessing rule to adapters 
(#3288)
f8a96ec002 is described below

commit f8a96ec00227c04e3f38ac4dbbea4561ad43d520
Author: Philipp Zehnder <[email protected]>
AuthorDate: Tue Oct 8 07:05:33 2024 +0200

    feat(#3282): regex based preprocessing rule to adapters (#3288)
    
    * feat(#3282): Add new rule and rule description for regex rule
    
    * feat(#3282): Add a regex rule for string event properties to connect
    
    * feat(#3282): Fix import in model client
---
 .../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/TransformationRuleUpdateVisitor.java   |   8 ++
 .../connect/rules/ITransformationRuleVisitor.java  |   3 +
 .../rules/TransformationRuleDescription.java       |   2 +
 .../connect/rules/TransformationRulePriority.java  |   1 +
 .../value/RegexTransformationRuleDescription.java  |  75 +++++++++++++++
 .../value/ValueTransformationRuleDescription.java  |   1 +
 .../storage/couchdb/serializer/GsonSerializer.java |   3 +
 .../connect/regexRule/expectedReplaceAllFalse.csv  |   2 +
 .../connect/regexRule/expectedReplaceAllTrue.csv   |   2 +
 .../expectedReplaceAllTrueWithEmptyString.csv      |   2 +
 ui/cypress/fixtures/connect/regexRule/input.csv    |   2 +
 .../utils/connect/ConnectEventSchemaUtils.ts       |  17 +++-
 .../connect/rules/deleteTransformationRule.spec.ts |  12 +--
 ui/cypress/tests/connect/rules/regexRule.spec.ts   | 107 +++++++++++++++++++++
 .../src/lib/model/gen/streampipes-model-client.ts  |   3 +-
 .../src/lib/model/gen/streampipes-model.ts         |  37 ++++++-
 .../src/lib/model/types/data-type.ts               |   4 +
 ui/src/app/connect/connect.module.ts               |   2 +
 .../edit-regex-transformation.component.html       |  52 ++++++++++
 .../edit-regex-transformation.component.scss       |  31 ------
 .../edit-regex-transformation.component.ts         |  39 ++------
 .../edit-value-transformation.component.html       |  10 ++
 .../edit-value-transformation.component.ts         |   1 +
 .../edit-event-property.component.html             |  12 +--
 .../edit-event-property.component.ts               |  18 ++++
 .../services/transformation-rule.service.ts        |  63 ++++++++++++
 35 files changed, 718 insertions(+), 118 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-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/TransformationRuleUpdateVisitor.java
 
b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/TransformationRuleUpdateVisitor.java
index ef357e4c48..9661b7705c 100644
--- 
a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/TransformationRuleUpdateVisitor.java
+++ 
b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/TransformationRuleUpdateVisitor.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;
@@ -80,6 +81,13 @@ public class TransformationRuleUpdateVisitor implements 
ITransformationRuleVisit
     }
   }
 
+  @Override
+  public void visit(RegexTransformationRuleDescription rule) {
+    if (containsKey(rule.getRuntimeKey())) {
+      validRules.add(rule);
+    }
+  }
+
   @Override
   public void visit(EventRateTransformationRuleDescription rule) {
     // Do nothing
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/TransformationRuleDescription.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java
index 0ea2194456..94b1817e8f 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRuleDescription.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;
 import org.apache.streampipes.model.shared.annotation.TsModel;
@@ -47,6 +48,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
     @JsonSubTypes.Type(CreateNestedRuleDescription.class),
     @JsonSubTypes.Type(DeleteRuleDescription.class),
     @JsonSubTypes.Type(RenameRuleDescription.class),
+    @JsonSubTypes.Type(RegexTransformationRuleDescription.class),
     @JsonSubTypes.Type(MoveRuleDescription.class),
     @JsonSubTypes.Type(ChangeDatatypeTransformationRuleDescription.class),
     @JsonSubTypes.Type(CorrectionValueTransformationRuleDescription.class),
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 {
 
diff --git 
a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
 
b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
index 685db7ee03..fee35a57a3 100644
--- 
a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
+++ 
b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/GsonSerializer.java
@@ -35,6 +35,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.grounding.TopicDefinition;
@@ -94,6 +95,8 @@ public class GsonSerializer {
 
     
builder.registerTypeAdapterFactory(RuntimeTypeAdapterFactory.of(TransformationRuleDescription.class,
 "sourceType")
         .registerSubtype(RenameRuleDescription.class, 
"org.apache.streampipes.model.RenameRuleDescription")
+        .registerSubtype(RegexTransformationRuleDescription.class,
+                         
"org.apache.streampipes.model.RegexTransformationRuleDescription")
         .registerSubtype(MoveRuleDescription.class, 
"org.apache.streampipes.model.MoveRuleDescription")
         .registerSubtype(DeleteRuleDescription.class, 
"org.apache.streampipes.model.DeleteRuleDescription")
         .registerSubtype(CreateNestedRuleDescription.class, 
"org.apache.streampipes.model.CreateNestedRuleDescription")
diff --git a/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllFalse.csv 
b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllFalse.csv
new file mode 100644
index 0000000000..f951ba2245
--- /dev/null
+++ b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllFalse.csv
@@ -0,0 +1,2 @@
+density;sensorId
+122.0;aensor01
diff --git a/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrue.csv 
b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrue.csv
new file mode 100644
index 0000000000..cbff946483
--- /dev/null
+++ b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrue.csv
@@ -0,0 +1,2 @@
+density;sensorId
+122.0;aenaor01
diff --git 
a/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrueWithEmptyString.csv
 
b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrueWithEmptyString.csv
new file mode 100644
index 0000000000..91547295c5
--- /dev/null
+++ 
b/ui/cypress/fixtures/connect/regexRule/expectedReplaceAllTrueWithEmptyString.csv
@@ -0,0 +1,2 @@
+density;sensorId
+122.0;enor01
diff --git a/ui/cypress/fixtures/connect/regexRule/input.csv 
b/ui/cypress/fixtures/connect/regexRule/input.csv
new file mode 100644
index 0000000000..78eb36e07f
--- /dev/null
+++ b/ui/cypress/fixtures/connect/regexRule/input.csv
@@ -0,0 +1,2 @@
+timestamp;density;sensorId
+1720018277000;122.0;sensor01
diff --git a/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts 
b/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
index 6bcfe2b231..b8cdfeabeb 100644
--- a/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
@@ -255,6 +255,10 @@ export class ConnectEventSchemaUtils {
         cy.get('#event-schema-next-button').parent().should('not.be.disabled');
     }
 
+    public static schemaPreviewResultEvent() {
+        return cy.dataCy('schema-preview-result-event', { timeout: 10000 });
+    }
+
     public static finishEventSchemaConfiguration() {
         // Click next
         cy.dataCy('sp-connect-schema-editor', { timeout: 10000 }).should(
@@ -270,7 +274,18 @@ export class ConnectEventSchemaUtils {
         ConnectEventSchemaUtils.validateRuntimeName(propertyName);
     }
 
-    //
+    public static regexValueInput() {
+        return cy.dataCy('regex-value');
+    }
+
+    public static regexReplaceWithValueInput() {
+        return cy.dataCy('regex-replace-with-value');
+    }
+
+    public static regexReplaceAllCheckbox() {
+        return cy.dataCy('regex-replace-all-value');
+    }
+
     /**
      * Function to escape special characters in a string for use in Cypress
      * selectors
diff --git a/ui/cypress/tests/connect/rules/deleteTransformationRule.spec.ts 
b/ui/cypress/tests/connect/rules/deleteTransformationRule.spec.ts
index ad558ab8d2..19efb96b46 100644
--- a/ui/cypress/tests/connect/rules/deleteTransformationRule.spec.ts
+++ b/ui/cypress/tests/connect/rules/deleteTransformationRule.spec.ts
@@ -37,7 +37,7 @@ describe('Connect delete rule transformation', () => {
         ConnectEventSchemaUtils.deleteProperty('reserved bit_1');
         ConnectEventSchemaUtils.deleteProperty('reserved bit_2');
 
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
             '{\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01715356080000}',
         );
@@ -69,7 +69,7 @@ describe('Connect delete rule transformation', () => {
         ConnectEventSchemaUtils.deleteProperty('child');
 
         // The resulting string contains non-breaking spaces character (\u00A0)
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
             
'{\u00A0\u00A0\u00A0\u00A0"parent":\u00A0{\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0"child_two":\u00A0"textTwo"\u00A0\u00A0\u00A0\u00A0},\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01667904471000}',
         );
@@ -78,7 +78,7 @@ describe('Connect delete rule transformation', () => {
 
         // Test to delete the parent property
         ConnectEventSchemaUtils.deleteProperty('parent');
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
 
             '{\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01667904471000}',
@@ -88,7 +88,7 @@ describe('Connect delete rule transformation', () => {
         ConnectEventSchemaUtils.deleteProperty('child');
         ConnectEventSchemaUtils.deleteProperty('child_two');
 
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
             
'{\u00A0\u00A0\u00A0\u00A0"parent":\u00A0{},\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01667904471000}',
         );
@@ -97,7 +97,7 @@ describe('Connect delete rule transformation', () => {
 
         // Test to delete the parent property
         ConnectEventSchemaUtils.deleteProperty('parent');
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
 
             '{\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01667904471000}',
@@ -109,7 +109,7 @@ describe('Connect delete rule transformation', () => {
         ConnectEventSchemaUtils.deleteProperty('child');
         ConnectEventSchemaUtils.deleteProperty('child_two');
 
-        cy.dataCy('schema-preview-result-event').should(
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
             'have.text',
             
'{\u00A0\u00A0\u00A0\u00A0"parent":\u00A0{},\u00A0\u00A0\u00A0\u00A0"timestamp":\u00A01667904471000}',
         );
diff --git a/ui/cypress/tests/connect/rules/regexRule.spec.ts 
b/ui/cypress/tests/connect/rules/regexRule.spec.ts
new file mode 100644
index 0000000000..c9ac4d194a
--- /dev/null
+++ b/ui/cypress/tests/connect/rules/regexRule.spec.ts
@@ -0,0 +1,107 @@
+/*
+ *  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.
+ *
+ */
+
+/*
+ *  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.
+ *
+ */
+
+import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
+import { ConnectEventSchemaUtils } from 
'../../../support/utils/connect/ConnectEventSchemaUtils';
+import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+import { FileManagementUtils } from 
'../../../support/utils/FileManagementUtils';
+
+describe('Connect value rule transformations', () => {
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+        FileManagementUtils.addFile('connect/regexRule/input.csv');
+    });
+
+    it('Perform Test Replace All True', () => {
+        runTest('aenaor01', 'a', true, 'expectedReplaceAllTrue.csv');
+    });
+
+    it('Perform Test Replace All False', () => {
+        runTest('aensor01', 'a', false, 'expectedReplaceAllFalse.csv');
+    });
+
+    it('Perform Test Replace With Empty String', () => {
+        runTest(
+            'enor01',
+            '',
+            true,
+            'expectedReplaceAllTrueWithEmptyString.csv',
+        );
+    });
+
+    function runTest(
+        expectedPreview: string,
+        replaceWith: string,
+        replaceAll: boolean,
+        expecedCsvFile: string,
+    ) {
+        const adapterConfiguration =
+            ConnectUtils.setUpPreprocessingRuleTest(false);
+
+        // Ensure regex input is not shown for number property
+        ConnectEventSchemaUtils.clickEditProperty('density');
+        ConnectEventSchemaUtils.regexValueInput().should('not.exist');
+        ConnectBtns.saveEditProperty().click();
+        ConnectEventSchemaUtils.clickEditProperty('sensorId');
+        ConnectEventSchemaUtils.regexValueInput().should('be.visible');
+
+        // Validate that preview works
+        ConnectEventSchemaUtils.regexValueInput().type('s');
+        if (replaceWith !== '') {
+            ConnectEventSchemaUtils.regexReplaceWithValueInput().type(
+                replaceWith,
+            );
+        }
+        if (replaceAll) {
+            ConnectEventSchemaUtils.regexReplaceAllCheckbox().click();
+        }
+
+        ConnectBtns.saveEditProperty().click();
+
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().should(
+            'contain.text',
+            expectedPreview,
+        );
+        ConnectEventSchemaUtils.markPropertyAsTimestamp('timestamp');
+        ConnectEventSchemaUtils.finishEventSchemaConfiguration();
+
+        ConnectUtils.tearDownPreprocessingRuleTest(
+            adapterConfiguration,
+            'cypress/fixtures/connect/regexRule/' + expecedCsvFile,
+            true,
+        );
+    }
+});
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
index 4cbe0f01c0..68e4a75c60 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-09-08 
22:18:46.
+// Generated using typescript-generator version 3.2.1263 on 2024-10-07 
13:58:29.
 
 import { Storable } from './streampipes-model';
 
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 1ae8e4e32d..e5faa9118d 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-09-30 
14:11:40.
+// Generated using typescript-generator version 3.2.1263 on 2024-10-07 
13:58:27.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -209,6 +208,7 @@ export class TransformationRuleDescription {
         | 
'org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription'
+        | 
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.stream.StreamTransformationRuleDescription'
@@ -261,6 +261,8 @@ export class TransformationRuleDescription {
                 return DeleteRuleDescription.fromData(data);
             case 
'org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription':
                 return RenameRuleDescription.fromData(data);
+            case 
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription':
+                return RegexTransformationRuleDescription.fromData(data);
             case 
'org.apache.streampipes.model.connect.rules.schema.MoveRuleDescription':
                 return MoveRuleDescription.fromData(data);
             case 
'org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription':
@@ -282,6 +284,7 @@ export class ValueTransformationRuleDescription extends 
TransformationRuleDescri
         | 
'org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.TimestampTranfsformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription'
+        | 
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.ChangeDatatypeTransformationRuleDescription'
         | 
'org.apache.streampipes.model.connect.rules.value.CorrectionValueTransformationRuleDescription';
 
@@ -316,6 +319,8 @@ export class ValueTransformationRuleDescription extends 
TransformationRuleDescri
                 return CorrectionValueTransformationRuleDescription.fromData(
                     data,
                 );
+            case 
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription':
+                return RegexTransformationRuleDescription.fromData(data);
         }
     }
 }
@@ -3061,6 +3066,30 @@ export class QuantitativeValue extends 
ValueSpecification {
     }
 }
 
+export class RegexTransformationRuleDescription extends 
ValueTransformationRuleDescription {
+    '@class': 
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription';
+    'regex': string;
+    'replaceAll': boolean;
+    'replaceWith': string;
+    'runtimeKey': string;
+
+    static 'fromData'(
+        data: RegexTransformationRuleDescription,
+        target?: RegexTransformationRuleDescription,
+    ): RegexTransformationRuleDescription {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new RegexTransformationRuleDescription();
+        super.fromData(data, instance);
+        instance.regex = data.regex;
+        instance.replaceAll = data.replaceAll;
+        instance.replaceWith = data.replaceWith;
+        instance.runtimeKey = data.runtimeKey;
+        return instance;
+    }
+}
+
 export class RemoveDuplicatesTransformationRuleDescription extends 
StreamTransformationRuleDescription {
     '@class': 
'org.apache.streampipes.model.connect.rules.stream.RemoveDuplicatesTransformationRuleDescription';
     'filterTimeWindow': string;
@@ -4080,6 +4109,7 @@ export type TransformationRuleDescriptionUnion =
     | CreateNestedRuleDescription
     | DeleteRuleDescription
     | RenameRuleDescription
+    | RegexTransformationRuleDescription
     | MoveRuleDescription
     | ChangeDatatypeTransformationRuleDescription
     | CorrectionValueTransformationRuleDescription;
@@ -4100,7 +4130,8 @@ export type ValueTransformationRuleDescriptionUnion =
     | AddValueTransformationRuleDescription
     | TimestampTranfsformationRuleDescription
     | UnitTransformRuleDescription
-    | CorrectionValueTransformationRuleDescription;
+    | CorrectionValueTransformationRuleDescription
+    | RegexTransformationRuleDescription;
 
 function __getCopyArrayFn<T>(itemCopyFn: (item: T) => T): (array: T[]) => T[] {
     return (array: T[]) => __copyArray(array, itemCopyFn);
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/types/data-type.ts 
b/ui/projects/streampipes/platform-services/src/lib/model/types/data-type.ts
index 077b9b9741..74e75ac9ea 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/types/data-type.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/types/data-type.ts
@@ -41,4 +41,8 @@ export class DataType {
     public static isBooleanType(datatype: string): boolean {
         return datatype === DataType.BOOLEAN;
     }
+
+    public static isStringType(datatype: string): boolean {
+        return datatype === DataType.STRING;
+    }
 }
diff --git a/ui/src/app/connect/connect.module.ts 
b/ui/src/app/connect/connect.module.ts
index 0d0e598a31..f66f7edebb 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -104,6 +104,7 @@ import { AdapterStatusLightComponent } from 
'./components/existing-adapters/adap
 import { SpAdapterDeploymentSettingsComponent } from 
'./components/adapter-configuration/adapter-settings/adapter-deployment-settings/adapter-deployment-settings.component';
 import { SpAdapterDocumentationDialogComponent } from 
'./dialog/adapter-documentation/adapter-documentation-dialog.component';
 import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapter-details-data/adapter-details-data.component';
+import { EditRegexTransformationComponent } from 
'./dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component';
 
 @NgModule({
     imports: [
@@ -204,6 +205,7 @@ import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapte
         DeleteAdapterDialogComponent,
         EventSchemaComponent,
         EditEventPropertyComponent,
+        EditRegexTransformationComponent,
         EventPropertyRowComponent,
         EditUnitTransformationComponent,
         EditSchemaTransformationComponent,
diff --git 
a/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.html
 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.html
new file mode 100644
index 0000000000..e75269a4c2
--- /dev/null
+++ 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.html
@@ -0,0 +1,52 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
+<div fxLayout="column" fxLayoutAlign="start">
+    <div fxFlex="50" fxLayoutAlign="start center">
+        <mat-form-field class="w-100" color="accent">
+            <input
+                matInput
+                type="text"
+                name="regex"
+                placeholder="Regular expression"
+                data-cy="regex-value"
+                [(ngModel)]="cachedProperty.additionalMetadata.regex"
+            />
+        </mat-form-field>
+    </div>
+    <div fxFlex="50" fxLayoutAlign="start center">
+        <mat-form-field class="w-100" color="accent">
+            <input
+                matInput
+                type="text"
+                name="replaceWith"
+                placeholder="Replace with"
+                data-cy="regex-replace-with-value"
+                [(ngModel)]="cachedProperty.additionalMetadata.replaceWith"
+            />
+        </mat-form-field>
+    </div>
+    <div fxFlex="50" fxLayoutAlign="start center">
+        <mat-checkbox
+            data-cy="regex-replace-all-value"
+            [(ngModel)]="cachedProperty.additionalMetadata.replaceAll"
+        >
+            <span>Replace All Occurrences</span>
+        </mat-checkbox>
+    </div>
+</div>
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.scss
similarity index 61%
copy from 
streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
copy to 
ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.scss
index 3fcb8ba429..13cbc4aacb 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
+++ 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.scss
@@ -15,34 +15,3 @@
  * limitations under the License.
  *
  */
-
-package org.apache.streampipes.model.connect.rules;
-
-public enum TransformationRulePriority {
-
-  ADD_TIMESTAMP(100),
-  ADD_VALUE(110),
-
-  RENAME(210),
-  CREATE_NESTED(230),
-  MOVE(235),
-  DELETE(240),
-
-  CHANGE_UNIT(310),
-  TIMESTAMP_TRANSFORMATION(320),
-  CORRECTION_VALUE(330),
-  CHANGE_DATATYPE(340),
-
-  REMOVE_DUPLICATES(410),
-  EVENT_RATE(420);
-
-  private final int code;
-
-  TransformationRulePriority(int code) {
-    this.code = code;
-  }
-
-  public int getCode() {
-    return this.code;
-  }
-}
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.ts
similarity index 61%
copy from 
streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
copy to 
ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.ts
index 3fcb8ba429..f926738e0e 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/rules/TransformationRulePriority.java
+++ 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-regex-transformation/edit-regex-transformation.component.ts
@@ -16,33 +16,14 @@
  *
  */
 
-package org.apache.streampipes.model.connect.rules;
-
-public enum TransformationRulePriority {
-
-  ADD_TIMESTAMP(100),
-  ADD_VALUE(110),
-
-  RENAME(210),
-  CREATE_NESTED(230),
-  MOVE(235),
-  DELETE(240),
-
-  CHANGE_UNIT(310),
-  TIMESTAMP_TRANSFORMATION(320),
-  CORRECTION_VALUE(330),
-  CHANGE_DATATYPE(340),
-
-  REMOVE_DUPLICATES(410),
-  EVENT_RATE(420);
-
-  private final int code;
-
-  TransformationRulePriority(int code) {
-    this.code = code;
-  }
-
-  public int getCode() {
-    return this.code;
-  }
+import { Component, Input } from '@angular/core';
+import { EventPropertyUnion } from '@streampipes/platform-services';
+
+@Component({
+    selector: 'sp-edit-regex-transformation',
+    templateUrl: './edit-regex-transformation.component.html',
+    styleUrl: './edit-regex-transformation.component.scss',
+})
+export class EditRegexTransformationComponent {
+    @Input() cachedProperty: EventPropertyUnion;
 }
diff --git 
a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
index 5986d8137d..9cfb5cc517 100644
--- 
a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
+++ 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.html
@@ -60,4 +60,14 @@
             />
         </mat-form-field>
     </sp-ep-settings-section>
+    <sp-ep-settings-section
+        sectionTitle="Regex Value Transformation"
+        sectionDescription="Transforms the original field values using the 
provided regex"
+        fxLayout="column"
+        fxFlex="100"
+        *ngIf="isStringProperty"
+    >
+        <sp-edit-regex-transformation [cachedProperty]="cachedProperty">
+        </sp-edit-regex-transformation>
+    </sp-ep-settings-section>
 </div>
diff --git 
a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
index fd87bf99a1..73238f6d3c 100644
--- 
a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
+++ 
b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-value-transformation.component.ts
@@ -40,6 +40,7 @@ export class EditValueTransformationComponent implements 
OnInit {
     @Input() isListProperty: boolean;
     @Input() isPrimitiveProperty: boolean;
     @Input() isNumericProperty: boolean;
+    @Input() isStringProperty: boolean;
 
     addedByUser: boolean;
     staticValue: string;
diff --git 
a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
 
b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
index 0fe15aea50..cc7aad6cad 100644
--- 
a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
+++ 
b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.html
@@ -82,6 +82,7 @@
                         [isNestedProperty]="isEventPropertyNested"
                         [isListProperty]="isEventPropertyList"
                         [isPrimitiveProperty]="isEventPropertyPrimitive"
+                        [isStringProperty]="isStringProperty"
                         #valueTransformationComponent
                     >
                     </sp-edit-value-transformation>
@@ -98,17 +99,6 @@
                     </sp-edit-unit-transformation>
                 </div>
             </form>
-
-            <!--            <sp-edit-event-property-primitive-->
-            <!--                    *ngIf="isEventPropertyPrimitive"-->
-            <!--                    
[isTimestampProperty]="isTimestampProperty"-->
-            <!--                    [cachedProperty]="cachedProperty"-->
-            <!--                    
(isNumericDataType)="isNumericDataType($event)">-->
-            <!--            </sp-edit-event-property-primitive>-->
-            <!--            <sp-edit-event-property-list-->
-            <!--                    *ngIf="isEventPropertyList"-->
-            <!--                    [cachedProperty]="cachedProperty">-->
-            <!--            </sp-edit-event-property-list>-->
         </div>
     </div>
     <mat-divider></mat-divider>
diff --git 
a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
 
b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
index 0cff8aefd4..ea7f191aca 100644
--- 
a/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
+++ 
b/ui/src/app/connect/dialog/edit-event-property/edit-event-property.component.ts
@@ -66,6 +66,7 @@ export class EditEventPropertyComponent implements OnInit {
     isEventPropertyNested: boolean;
     isEventPropertyList: boolean;
     isNumericProperty: boolean;
+    isStringProperty: boolean;
     isSaveBtnEnabled: boolean;
 
     private propertyForm: UntypedFormGroup;
@@ -89,6 +90,9 @@ export class EditEventPropertyComponent implements OnInit {
         this.isNumericProperty =
             SemanticType.isNumber(this.cachedProperty) ||
             DataType.isNumberType((this.cachedProperty as any).runtimeType);
+        this.isStringProperty = DataType.isStringType(
+            (this.cachedProperty as any).runtimeType,
+        );
         this.createForm();
     }
 
@@ -116,6 +120,13 @@ export class EditEventPropertyComponent implements OnInit {
                     ep.additionalMetadata.formatString;
                 result.additionalMetadata.multiplier =
                     ep.additionalMetadata.multiplier;
+
+                result.additionalMetadata.regex =
+                    ep.additionalMetadata.regex || undefined;
+                result.additionalMetadata.replaceWith =
+                    ep.additionalMetadata.replaceWith || undefined;
+                result.additionalMetadata.replaceAll =
+                    ep.additionalMetadata.replaceAll || undefined;
             }
 
             (result as any).staticValue = (ep as any).staticValue;
@@ -177,6 +188,13 @@ export class EditEventPropertyComponent implements OnInit {
                 this.cachedProperty.additionalMetadata.correctionValue;
             this.property.additionalMetadata.operator =
                 this.cachedProperty.additionalMetadata.operator;
+
+            this.property.additionalMetadata.regex =
+                this.cachedProperty.additionalMetadata.regex;
+            this.property.additionalMetadata.replaceWith =
+                this.cachedProperty.additionalMetadata.replaceWith;
+            this.property.additionalMetadata.replaceAll =
+                this.cachedProperty.additionalMetadata.replaceAll;
         }
         this.dialogRef.close({ data: this.property });
         this.shepherdService.trigger('adapter-field-changed');
diff --git a/ui/src/app/connect/services/transformation-rule.service.ts 
b/ui/src/app/connect/services/transformation-rule.service.ts
index b79883961a..5d87c36d69 100644
--- a/ui/src/app/connect/services/transformation-rule.service.ts
+++ b/ui/src/app/connect/services/transformation-rule.service.ts
@@ -31,6 +31,7 @@ import {
     EventSchema,
     MoveRuleDescription,
     PropertyScope,
+    RegexTransformationRuleDescription,
     RenameRuleDescription,
     SemanticType,
     TimestampTranfsformationRuleDescription,
@@ -100,6 +101,13 @@ export class TransformationRuleService {
 
             // Scale
             transformationRuleDescriptions = transformationRuleDescriptions
+                .concat(
+                    this.getRegexTransformationRules(
+                        targetSchema.eventProperties,
+                        originalSchema,
+                        targetSchema,
+                    ),
+                )
                 .concat(
                     this.getCorrectionValueRules(
                         targetSchema.eventProperties,
@@ -671,4 +679,59 @@ export class TransformationRuleService {
 
         return filteredResult;
     }
+
+    private getRegexTransformationRules(
+        eventProperties: EventPropertyUnion[],
+        oldEventSchema: EventSchema,
+        newEventSchema: EventSchema,
+    ) {
+        const result: RegexTransformationRuleDescription[] = [];
+
+        eventProperties.forEach(eventProperty => {
+            if (eventProperty instanceof EventPropertyPrimitive) {
+                const newRuntimeName = this.getCompleteRuntimeNameKey(
+                    newEventSchema.eventProperties,
+                    eventProperty.elementId,
+                );
+
+                if (
+                    eventProperty.additionalMetadata?.regex &&
+                    eventProperty.additionalMetadata?.regex != ''
+                ) {
+                    const rule =
+                        
this.createRegexTransformationRuleDescriptionFromEventProperty(
+                            newRuntimeName,
+                            eventProperty,
+                        );
+
+                    result.push(rule);
+                }
+            } else if (eventProperty instanceof EventPropertyNested) {
+                result.push(
+                    ...this.getRegexTransformationRules(
+                        eventProperty.eventProperties,
+                        oldEventSchema,
+                        newEventSchema,
+                    ),
+                );
+            }
+        });
+
+        return result;
+    }
+
+    private createRegexTransformationRuleDescriptionFromEventProperty(
+        newRuntimeName: string,
+        eventProperty: EventPropertyPrimitive,
+    ) {
+        const rule: RegexTransformationRuleDescription =
+            new RegexTransformationRuleDescription();
+        rule['@class'] =
+            
'org.apache.streampipes.model.connect.rules.value.RegexTransformationRuleDescription';
+        rule.runtimeKey = newRuntimeName;
+        rule.regex = eventProperty.additionalMetadata.regex;
+        rule.replaceWith = eventProperty.additionalMetadata.replaceWith ?? '';
+        rule.replaceAll = eventProperty.additionalMetadata.replaceAll ?? false;
+        return rule;
+    }
 }

Reply via email to