Repository: apache/streampipes (java)

Issue:
Compiling maven submodule with checkstyle check
### Body

When attempting to compile a single Maven module, an error message appears stating that the file  `tools/maven/checkstyle-header.txt` could not be found [1].
This occurs because the path is only correct when the Maven command is executed in the root directory.

What do you think about the idea of defining a variable that points to the correct location? 

I have tested this with Maven, Eclipse, and IntelliJ and have not encountered any issues so far. 
If the variable is not set, the default path will be used, which means that no changes are necessary.

[1]  `[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.2.2:check (validate) on project streampipes-messaging-mqtt: Failed during checkstyle configuration: cannot initialize module Header - illegal value 'tools/maven/checkstyle-header.txt' for property 'headerFile': com.puppycrawl.tools.checkstyle.api.CheckstyleException: Unable to find: tools/maven/checkstyle-header.txt -> [Help 1]`


### StreamPipes Committer

I acknowledge that I am a maintainer/committer of the Apache StreamPipes project.

Pull request description:
#1518 Add variable to set location of checkstyle base path

fixes #1518


Patch:
diff --git a/.github/workflows/python-docs.yml b/.github/workflows/python-docs.yml
index 19023a3098..6581ee030e 100644
--- a/.github/workflows/python-docs.yml
+++ b/.github/workflows/python-docs.yml
@@ -56,8 +56,7 @@ jobs:
       - name: Build Python docs
         working-directory: ./streampipes-client-python
         run: |
-          mike deploy dev latest -u --deploy-prefix ./streampipes-client-python/docs-tmp -b build-python-docs-${{ github.run_id }}
-          mike set-default latest --deploy-prefix ./streampipes-client-python/docs-tmp -b build-python-docs-${{ github.run_id }}
+          mike deploy dev -u --deploy-prefix ./streampipes-client-python/docs-tmp -b build-python-docs-${{ github.run_id }}
           git reset --hard  # undo local changes that delete generated doc files
 
       - name: Publish Python docs as artifact
diff --git a/streampipes-client/pom.xml b/streampipes-client/pom.xml
index f24e663780..25c96b1a12 100644
--- a/streampipes-client/pom.xml
+++ b/streampipes-client/pom.xml
@@ -97,8 +97,13 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <propertyExpansion>
+                		checkstyle.config.base.path=${project.parent.basedir}/tools/maven
+                	</propertyExpansion>
+                </configuration>
             </plugin>
         </plugins>
     </build>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/preprocessing/transform/value/CorrectionValueTransformationRule.java b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/preprocessing/transform/value/CorrectionValueTransformationRule.java
index 4b1f6f838a..e720e4b27c 100644
--- a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/preprocessing/transform/value/CorrectionValueTransformationRule.java
+++ b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/preprocessing/transform/value/CorrectionValueTransformationRule.java
@@ -49,26 +49,22 @@ public class CorrectionValueTransformationRule implements ValueTransformationRul
     if (eventKey.size() == 1) {
       try {
         Object obj = event.get(eventKey.get(0));
-        double old = 0d;
+        double old;
         if (obj instanceof Number) {
           old = ((Number) obj).doubleValue();
+        } else {
+          throw new RuntimeException(
+              String.format("Selected property `%s` does not contain a numeric value: `%s", eventKey.get(0), obj)
+          );
         }
 
-        double corrected = 0d;
-        switch (operator) {
-          case "MULTIPLY":
-            corrected = old * correctionValue;
-            break;
-          case "ADD":
-            corrected = old + correctionValue;
-            break;
-          case "SUBSTRACT":
-            corrected = old - correctionValue;
-            break;
-          default:
-            corrected = old;
-            break;
-        }
+        double corrected = switch (operator) {
+          case "MULTIPLY" -> old * correctionValue;
+          case "ADD" -> old + correctionValue;
+          case "SUBTRACT" -> old - correctionValue;
+          case "DIVIDE" -> old / correctionValue;
+          default -> old;
+        };
 
         event.put(eventKey.get(0), corrected);
       } catch (ClassCastException e) {
diff --git a/streampipes-rest-extensions/pom.xml b/streampipes-rest-extensions/pom.xml
index d95d3e45de..192260917d 100644
--- a/streampipes-rest-extensions/pom.xml
+++ b/streampipes-rest-extensions/pom.xml
@@ -75,4 +75,4 @@
         </plugins>
     </build>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/streampipes-rest-shared/pom.xml b/streampipes-rest-shared/pom.xml
index de74e640dc..e94975373e 100644
--- a/streampipes-rest-shared/pom.xml
+++ b/streampipes-rest-shared/pom.xml
@@ -17,7 +17,8 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <artifactId>streampipes-parent</artifactId>
         <groupId>org.apache.streampipes</groupId>
diff --git a/streampipes-rest/pom.xml b/streampipes-rest/pom.xml
index 64eb418d7c..94bcca3803 100644
--- a/streampipes-rest/pom.xml
+++ b/streampipes-rest/pom.xml
@@ -159,7 +159,12 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <propertyExpansion>
+                        checkstyle.config.base.path=${project.parent.basedir}/tools/maven
+                    </propertyExpansion>
+                </configuration>
             </plugin>
         </plugins>
     </build>
-</project>
+</project>
\ No newline at end of file
diff --git a/tools/maven/checkstyle.xml b/tools/maven/checkstyle.xml
index 83861dbe07..a86ef413dc 100644
--- a/tools/maven/checkstyle.xml
+++ b/tools/maven/checkstyle.xml
@@ -28,7 +28,7 @@ page at http://checkstyle.sourceforge.net/config.html -->
     <property name="severity" value="error"/>
 
     <module name="Header">
-        <property name="headerFile" value="tools/maven/checkstyle-header.txt"/>
+        <property name="headerFile" value="${checkstyle.config.base.path}/checkstyle-header.txt" default="tools/maven/checkstyle-header.txt"/>
         <property name="fileExtensions" value="java"/>
     </module>
 
diff --git a/ui/README.md b/ui/README.md
index 91c19f6eb6..3f3ce4304e 100644
--- a/ui/README.md
+++ b/ui/README.md
@@ -43,4 +43,4 @@ To test your local version of the UI execute the following commands:
 Running `npm install` will cause a pre-commit hook to be created.
 This hook ensures that if you want to commit changes to this repository, these changes are compliant with our [formatting](https://prettier.io/) and [linting](https://eslint.org/) rules.
 
-If you see errors there, you can try to run `npm run format:fix` and `npm run lint:fix` to fix these issues automatically. Otherwise you have to run `npm run format` and `npm run lint` to get additional information about the problems.
+If you see errors there, you can try to run `npm run format:fix` and `npm run lint:fix` to fix these issues automatically. Otherwise, you have to run `npm run format` and `npm run lint` to get additional information about the problems.
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts
index 90e17883ce..87b31c9fd1 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-value-transformation/edit-correction-value/edit-correction-value.component.ts
@@ -30,7 +30,8 @@ export class EditCorrectionValueComponent {
     operators = [
         { value: 'MULTIPLY', viewValue: 'Multiply' },
         { value: 'ADD', viewValue: 'Add' },
-        { value: 'SUBSTRACT', viewValue: 'Substract' },
+        { value: 'SUBTRACT', viewValue: 'Subtract' },
+        { value: 'DIVIDE', viewValue: 'Divide' },
     ];
 
     constructor() {}
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 df8839db8d..b2c98542c5 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
@@ -159,7 +159,7 @@ export class EditEventPropertyComponent implements OnInit {
         this.property.label = this.cachedProperty.label;
         this.property.description = this.cachedProperty.description;
 
-        // remove undefined from domain properies array
+        // remove undefined from domain properties array
         this.property.domainProperties =
             this.cachedProperty.domainProperties.filter(n => n);
         this.property.runtimeName = this.cachedProperty.runtimeName;


Test patch:
diff --git a/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/connect/adapter/transform/value/CorrectionValueTest.java b/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/connect/adapter/transform/value/CorrectionValueTest.java
new file mode 100644
index 0000000000..5bc26c26d8
--- /dev/null
+++ b/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/connect/adapter/transform/value/CorrectionValueTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.extensions.management.connect.adapter.transform.value;
+
+import org.apache.streampipes.extensions.management.connect.adapter.preprocessing.transform.value.CorrectionValueTransformationRule;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.schema.EventSchema;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+public class CorrectionValueTest {
+
+  private Map<String, Object> event;
+
+  private final String propertyNameBasicValue = "basicValue";
+  private final String propertyNameOtherValue = "otherValue";
+
+  @Before
+  public void setUp() {
+
+    EventSchema eventSchema = new EventSchema();
+    EventProperty eventProperty = new EventPropertyPrimitive();
+    eventProperty.setLabel(propertyNameBasicValue);
+    eventProperty.setRuntimeName(propertyNameBasicValue);
+    eventSchema.addEventProperty(eventProperty);
+
+    EventProperty eventPropertyOther = new EventPropertyPrimitive();
+    eventPropertyOther.setLabel(propertyNameBasicValue);
+    eventPropertyOther.setRuntimeName(propertyNameBasicValue);
+    eventSchema.addEventProperty(eventPropertyOther);
+
+    event = new HashMap<>();
+    event.put(propertyNameBasicValue, 100.0);
+    event.put(propertyNameOtherValue, "Hello");
+  }
+
+  @Test
+  public void testAdd() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+         List.of(propertyNameBasicValue),
+         10.0,
+         "ADD"
+     );
+
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(110.0, resultEvent.get(propertyNameBasicValue));
+  }
+
+  @Test
+  public void testSubtract() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameBasicValue),
+        10.0,
+        "SUBTRACT"
+    );
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(90.0, resultEvent.get(propertyNameBasicValue));
+  }
+
+  @Test
+  public void testMultiply() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameBasicValue),
+        1.5,
+        "MULTIPLY"
+    );
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(150.0, resultEvent.get(propertyNameBasicValue));
+  }
+
+  @Test
+  public void testDivide() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameBasicValue),
+        5,
+        "DIVIDE"
+    );
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(20.0, resultEvent.get(propertyNameBasicValue));
+  }
+
+  @Test
+  public void testDivideByZero() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameBasicValue),
+        0.0,
+        "DIVIDE"
+    );
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(Double.POSITIVE_INFINITY, resultEvent.get(propertyNameBasicValue));
+  }
+
+  @Test
+  public void testNonNumericValue() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameOtherValue),
+        10.0,
+        "ADD"
+    );
+    assertThrows (
+        String.format("Selected property `%s` does not contain a numeric value: `%s", propertyNameOtherValue, "Hello"),
+        RuntimeException.class,
+        () -> correctionRule.transform(event).get(propertyNameOtherValue)
+    );
+
+
+  }
+
+  @Test
+  public void testUnsupportedOperation() {
+
+    var correctionRule = new CorrectionValueTransformationRule(
+        List.of(propertyNameBasicValue),
+        10.0,
+        "TEST"
+    );
+    var resultEvent = correctionRule.transform(event);
+    assertNotNull(resultEvent);
+    assertEquals(100.0, resultEvent.get(propertyNameBasicValue));
+  }
+}