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 a69c54b9eb fix(#3506): connect static property type cannot be changed 
to numeric value (#3510)
a69c54b9eb is described below

commit a69c54b9ebf26715b6640b9977174dda40df64bd
Author: Philipp Zehnder <[email protected]>
AuthorDate: Fri Feb 28 10:25:50 2025 +0100

    fix(#3506): connect static property type cannot be changed to numeric value 
(#3510)
    
    * fix(#3506): Add test and fix bug when data type of static value is changed
    
    * fix(#3506): Fix edit adapter with add static and change data type rule
---
 .../convert/ToTransformedSchemaConverter.java      |  6 ++
 .../stream/EventRateTransformationRule.java        |  5 --
 .../connect/addNumericalStaticValue/expected.json  | 17 ++++
 .../connect/addNumericalStaticValue/input.csv      |  4 +
 ui/cypress/support/utils/DataSetUtils.ts           | 54 ++++++++++---
 .../utils/connect/ConnectEventSchemaUtils.ts       | 15 +++-
 ui/cypress/support/utils/datalake/DataLakeUtils.ts | 68 ++++++++++++----
 .../connect/rules/addNumericalStaticValue.spec.ts  | 85 ++++++++++++++++++++
 .../schema-editor-header.component.ts              |  1 +
 .../edit-value-transformation.component.ts         |  5 +-
 .../services/event-property-utils.service.ts       |  7 --
 .../services/static-value-transform.service.ts     | 42 ++++++++--
 .../services/transformation-rule.service.ts        | 90 +++++++++++++++++-----
 13 files changed, 333 insertions(+), 66 deletions(-)

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 00dcd7cc43..2a677fb89f 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
@@ -122,6 +122,10 @@ public class ToTransformedSchemaConverter implements 
ITransformationRuleVisitor,
   public void visit(AddValueTransformationRuleDescription rule) {
     var property = new EventPropertyPrimitive();
     property.setElementId(STATIC_VALUE_ID_PREFIX + rule.getStaticValue());
+    var uniqueId = UUIDGenerator.generateUuid().substring(0, 10);
+
+    property.setElementId(STATIC_VALUE_ID_PREFIX + uniqueId + ":" + 
rule.getStaticValue());
+
     property.setRuntimeName(rule.getRuntimeKey());
     property.setRuntimeType(rule.getDatatype());
     property.setLabel(rule.getLabel());
@@ -137,6 +141,8 @@ public class ToTransformedSchemaConverter implements 
ITransformationRuleVisitor,
     this.properties.add(property);
   }
 
+
+
   @Override
   public void visit(ChangeDatatypeTransformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
diff --git 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/stream/EventRateTransformationRule.java
 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/stream/EventRateTransformationRule.java
index b5b586f65e..2ef0b37629 100644
--- 
a/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/stream/EventRateTransformationRule.java
+++ 
b/streampipes-connect-shared/src/main/java/org/apache/streampipes/connect/shared/preprocessing/transform/stream/EventRateTransformationRule.java
@@ -43,11 +43,6 @@ public class EventRateTransformationRule implements 
TransformationRule {
         case "none":
           lastSentToPipelineTimestamp = System.currentTimeMillis();
           return event;
-//                case "max":
-//                case "min":
-//                case "mean":
-//                case "sum":
-
       }
     }
     return null;
diff --git a/ui/cypress/fixtures/connect/addNumericalStaticValue/expected.json 
b/ui/cypress/fixtures/connect/addNumericalStaticValue/expected.json
new file mode 100644
index 0000000000..844e16102f
--- /dev/null
+++ b/ui/cypress/fixtures/connect/addNumericalStaticValue/expected.json
@@ -0,0 +1,17 @@
+[
+  {
+    "count": 122.0,
+    "newValueOne": 1.0,
+    "newValueTwo": 2
+  },
+  {
+    "count": 123.0,
+    "newValueOne": 1.0,
+    "newValueTwo": 2
+  },
+  {
+    "count": 124.0,
+    "newValueOne": 1.0,
+    "newValueTwo": 2
+  }
+]
diff --git a/ui/cypress/fixtures/connect/addNumericalStaticValue/input.csv 
b/ui/cypress/fixtures/connect/addNumericalStaticValue/input.csv
new file mode 100644
index 0000000000..12af6ec571
--- /dev/null
+++ b/ui/cypress/fixtures/connect/addNumericalStaticValue/input.csv
@@ -0,0 +1,4 @@
+timestamp;count
+1720018277000;122.0
+1720018280000;123.0
+1720018285000;124.0
diff --git a/ui/cypress/support/utils/DataSetUtils.ts 
b/ui/cypress/support/utils/DataSetUtils.ts
index 48cf6a2a27..fec03f3afb 100644
--- a/ui/cypress/support/utils/DataSetUtils.ts
+++ b/ui/cypress/support/utils/DataSetUtils.ts
@@ -19,24 +19,60 @@
 import * as CSV from 'csv-string';
 
 export class DataSetUtils {
+    /**
+     * Compares two CSV strings for equality.
+     *
+     * @param actualCsv - The actual CSV string.
+     * @param expectedCsv - The expected CSV string.
+     * @param ignoreTime - Whether to ignore the timestamp field during 
comparison.
+     */
     public static csvEqual(
         actualCsv: string,
         expectedCsv: string,
         ignoreTime: boolean,
     ) {
-        let actualResult;
-        if (ignoreTime) {
-            actualResult = DataSetUtils.parseCsv(actualCsv).map(row => {
-                return row.splice(1);
-            });
-        } else {
-            actualResult = DataSetUtils.parseCsv(actualCsv);
-        }
+        const actualResult = ignoreTime
+            ? DataSetUtils.getActualResultIgnoringTime(actualCsv)
+            : DataSetUtils.parseCsv(actualCsv);
+
         const expectedResult = DataSetUtils.parseCsv(expectedCsv);
-        expect(actualResult).to.deep.equal(expectedResult);
+        DataSetUtils.compareCsvResults(actualResult, expectedResult);
+    }
+
+    private static getActualResultIgnoringTime(csv: string) {
+        return DataSetUtils.parseCsv(csv).map(row => row.splice(1));
     }
 
     private static parseCsv(csv: string) {
         return CSV.parse(csv, ';');
     }
+
+    private static compareCsvResults(
+        actualResult: any[],
+        expectedResult: any[],
+    ) {
+        expect(actualResult).to.deep.equal(expectedResult);
+    }
+
+    /**
+     * Compares two JSON strings for equality.
+     *
+     * @param actualJsonString - The actual JSON string.
+     * @param expectedJson - The expected JSON object.
+     * @param ignoreTime - Whether to ignore the timestamp field during 
comparison.
+     */
+    public static jsonFilesEqual(
+        actualJsonString: string,
+        expectedJson: any[],
+        ignoreTime: boolean,
+    ) {
+        const actualJson = JSON.parse(actualJsonString);
+
+        if (ignoreTime) {
+            actualJson.forEach((item: any) => delete item.timestamp);
+            expectedJson.forEach((item: any) => delete item.timestamp);
+        }
+
+        expect(actualJson).to.deep.equal(expectedJson);
+    }
 }
diff --git a/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts 
b/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
index b8cdfeabeb..b47213e93e 100644
--- a/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectEventSchemaUtils.ts
@@ -19,6 +19,14 @@
 import { ConnectBtns } from './ConnectBtns';
 
 export class ConnectEventSchemaUtils {
+    public static markPropertyAsMeasurement(propertyName: string) {
+        cy.dataCy('property-scope-' + propertyName, { timeout: 10000 })
+            .click()
+            .get('.mdc-list-item__primary-text')
+            .contains('Measurement')
+            .click();
+    }
+
     public static markPropertyAsDimension(propertyName: string) {
         cy.dataCy('property-scope-' + propertyName, { timeout: 10000 })
             .click()
@@ -175,8 +183,7 @@ export class ConnectEventSchemaUtils {
 
         // Edit new property
         cy.dataCy('connect-add-field-name', { timeout: 10000 }).type(
-            '{backspace}{backspace}{backspace}{backspace}{backspace}' +
-                propertyName,
+            propertyName,
         );
         cy.dataCy('connect-add-field-name-button').click();
 
@@ -231,7 +238,9 @@ export class ConnectEventSchemaUtils {
             .click();
         cy.dataCy('sp-save-edit-property').click();
         // validate that static value is persisted
-        cy.dataCy('edit-' + propertyName, { timeout: 10000 }).click({
+        cy.dataCy('edit-' + propertyName.toLowerCase(), {
+            timeout: 10000,
+        }).click({
             force: true,
         });
         ConnectBtns.changeRuntimeType().contains(dataType);
diff --git a/ui/cypress/support/utils/datalake/DataLakeUtils.ts 
b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
index 3102f82605..5ad599ad42 100644
--- a/ui/cypress/support/utils/datalake/DataLakeUtils.ts
+++ b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
@@ -413,29 +413,65 @@ export class DataLakeUtils {
     }
 
     public static checkResults(
-        dataLakeIndex: string,
+        measurementName: string,
         fileRoute: string,
+        ignoreTime: boolean,
+    ) {
+        const fileType = this.getFileType(fileRoute);
+
+        this.fetchDataLakeResults(measurementName, fileType).then(
+            actualResultString =>
+                this.compareResults(
+                    actualResultString,
+                    fileRoute,
+                    fileType,
+                    ignoreTime,
+                ),
+        );
+    }
+
+    private static getFileType(fileRoute: string): 'csv' | 'json' {
+        return fileRoute.endsWith('.csv') ? 'csv' : 'json';
+    }
+
+    private static fetchDataLakeResults(
+        measurementName: string,
+        fileType: 'csv' | 'json',
+    ): Cypress.Chainable<string> {
+        return cy
+            .request({
+                method: 'GET',
+                url: 
`/streampipes-backend/api/v4/datalake/measurements/${measurementName}/download?format=${fileType}&delimiter=semicolon`,
+                headers: {
+                    'content-type': 'application/octet-stream',
+                },
+                auth: {
+                    bearer: window.localStorage.getItem('auth-token'),
+                },
+            })
+            .then(response => response.body);
+    }
+
+    private static compareResults(
+        actualResultString: string,
+        fileRoute: string,
+        fileType: 'csv' | 'json',
         ignoreTime?: boolean,
     ) {
-        // Validate result in datalake
-        cy.request({
-            method: 'GET',
-            url: 
`/streampipes-backend/api/v4/datalake/measurements/${dataLakeIndex}/download?format=csv&delimiter=semicolon`,
-            headers: {
-                'content-type': 'application/octet-stream',
-            },
-            auth: {
-                bearer: window.localStorage.getItem('auth-token'),
-            },
-        }).then(response => {
-            const actualResultString = response.body;
-            cy.readFile(fileRoute).then(expectedResultString => {
+        cy.readFile(fileRoute).then(expectedResult => {
+            if (fileType === 'csv') {
                 DataSetUtils.csvEqual(
                     actualResultString,
-                    expectedResultString,
+                    expectedResult,
+                    ignoreTime,
+                );
+            } else if (fileType === 'json') {
+                DataSetUtils.jsonFilesEqual(
+                    actualResultString,
+                    expectedResult,
                     ignoreTime,
                 );
-            });
+            }
         });
     }
 
diff --git a/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts 
b/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts
new file mode 100644
index 0000000000..0745e6e247
--- /dev/null
+++ b/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts
@@ -0,0 +1,85 @@
+/*
+ *  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 { FileManagementUtils } from 
'../../../support/utils/FileManagementUtils';
+import { ConnectEventSchemaUtils } from 
'../../../support/utils/connect/ConnectEventSchemaUtils';
+import { DataLakeUtils } from '../../../support/utils/datalake/DataLakeUtils';
+import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+
+describe('Connect schema rule transformations', () => {
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+    });
+
+    it('Add a static property and transform it to a number', () => {
+        FileManagementUtils.addFile(
+            'connect/addNumericalStaticValue/input.csv',
+        );
+        const adapterConfiguration =
+            ConnectUtils.setUpPreprocessingRuleTest(false);
+
+        const newValueOne = 'newValueOne';
+        const newValueTwo = 'newValueTwo';
+
+        ConnectEventSchemaUtils.addStaticProperty(newValueOne, '1.0');
+        ConnectEventSchemaUtils.addStaticProperty(newValueTwo, '2');
+
+        ConnectEventSchemaUtils.changePropertyDataType(newValueOne, 'Float');
+        ConnectEventSchemaUtils.changePropertyDataType(newValueTwo, 'Integer');
+
+        ConnectEventSchemaUtils.markPropertyAsMeasurement(newValueOne);
+        ConnectEventSchemaUtils.markPropertyAsMeasurement(newValueTwo);
+
+        ConnectEventSchemaUtils.markPropertyAsTimestamp('timestamp');
+
+        ConnectEventSchemaUtils.finishEventSchemaConfiguration();
+
+        ConnectUtils.startAdapter(adapterConfiguration, true);
+
+        cy.wait(1000);
+
+        DataLakeUtils.checkResults(
+            'Adapter to test rules',
+            'cypress/fixtures/connect/addNumericalStaticValue/expected.json',
+            true,
+        );
+
+        ConnectUtils.goToConnect();
+        ConnectBtns.editAdapter().click();
+        // This waiting time is required to ensure that the file is loaded 
correctly before the next button is clicked
+        cy.wait(1000);
+        ConnectBtns.nextBtn().click();
+
+        // Validate that the preview is correct
+
+        const expectedJsonPreview = {
+            newValueTwo: 2,
+            count: 122,
+            timestamp: 1720018277000,
+            newValueOne: 1,
+        };
+        ConnectEventSchemaUtils.schemaPreviewResultEvent().then($el => {
+            let jsonPreview = $el.text();
+            jsonPreview = jsonPreview.replace(/\s+/g, '');
+
+            const actualJson = JSON.parse(jsonPreview);
+            expect(actualJson).to.deep.equal(expectedJsonPreview);
+        });
+    });
+});
diff --git 
a/ui/src/app/connect/components/adapter-configuration/schema-editor/schema-editor-header/schema-editor-header.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/schema-editor/schema-editor-header/schema-editor-header.component.ts
index 54fcdf0592..34f35d9c02 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/schema-editor/schema-editor-header/schema-editor-header.component.ts
+++ 
b/ui/src/app/connect/components/adapter-configuration/schema-editor/schema-editor-header/schema-editor-header.component.ts
@@ -47,6 +47,7 @@ export class SchemaEditorHeaderComponent {
 
     public addStaticValueProperty() {
         this.addStaticValuePropertyEmitter.emit(this.staticValueKey);
+        this.staticValueKey = '';
         this.trigger.closeMenu();
     }
 
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 73238f6d3c..0788ea4074 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
@@ -61,6 +61,9 @@ export class EditValueTransformationComponent implements 
OnInit {
 
     applyStaticValue(value: any) {
         this.cachedProperty.elementId =
-            this.staticValueTransformService.makeElementId(value);
+            this.staticValueTransformService.makeElementId(
+                this.cachedProperty.elementId,
+                value,
+            );
     }
 }
diff --git a/ui/src/app/connect/services/event-property-utils.service.ts 
b/ui/src/app/connect/services/event-property-utils.service.ts
index 22ba6ce6e7..2ed202712b 100644
--- a/ui/src/app/connect/services/event-property-utils.service.ts
+++ b/ui/src/app/connect/services/event-property-utils.service.ts
@@ -31,13 +31,6 @@ export class EventPropertyUtilsService {
         return this.findProperty(properties, elementId, ep => ep.elementId);
     }
 
-    findPropertyByRuntimeName(
-        properties: EventPropertyUnion[],
-        runtimeName: string,
-    ) {
-        return this.findProperty(properties, runtimeName, ep => 
ep.runtimeName);
-    }
-
     private findProperty(
         properties: EventPropertyUnion[],
         searchValue: string,
diff --git a/ui/src/app/connect/services/static-value-transform.service.ts 
b/ui/src/app/connect/services/static-value-transform.service.ts
index 7ba1ae0528..00c42e8b55 100644
--- a/ui/src/app/connect/services/static-value-transform.service.ts
+++ b/ui/src/app/connect/services/static-value-transform.service.ts
@@ -20,6 +20,17 @@ import { Injectable } from '@angular/core';
 import { IdGeneratorService } from 
'../../core-services/id-generator/id-generator.service';
 
 @Injectable({ providedIn: 'root' })
+/**
+ * This service provides methods to transform and handle static value 
properties.
+ *
+ * The format for static values is as follows:
+ *
+ * `http://eventProperty.de/staticValue/{uniqueId}:{value}`
+ *
+ * - `http://eventProperty.de/staticValue/` is the fixed prefix.
+ * - `{uniqueId}` is a unique identifier generated for each static value 
property.
+ * - `{value}` is the actual static value.
+ */
 export class StaticValueTransformService {
     prefix = 'http://eventProperty.de/staticValue/';
     placeholderValue = 'placeholder';
@@ -27,12 +38,12 @@ export class StaticValueTransformService {
     constructor(private idGeneratorService: IdGeneratorService) {}
 
     makeDefaultElementId(): string {
-        return this.getPrefix() + this.placeholderValue;
+        return this.getUniquePrefix() + this.placeholderValue;
     }
 
-    makeElementId(value: string) {
-        const lastSlashIndex = this.prefix.lastIndexOf('/');
-        const prefixWithId = this.prefix.substring(0, lastSlashIndex + 1);
+    makeElementId(elementId: string, value: string) {
+        const lastSlashIndex = elementId.lastIndexOf(':');
+        const prefixWithId = elementId.substring(0, lastSlashIndex + 1);
         return prefixWithId + value;
     }
 
@@ -41,11 +52,28 @@ export class StaticValueTransformService {
     }
 
     getStaticValue(elementId: string) {
-        const lastSlashIndex = elementId.lastIndexOf('/');
+        const lastSlashIndex = elementId.lastIndexOf(':');
         return elementId.substring(lastSlashIndex + 1);
     }
 
-    private getPrefix(): string {
-        return `${this.prefix + this.idGeneratorService.generate(10)}/`;
+    /**
+     * This is used to get a unique property prefix. The value of the static
+     * value will be appended
+     */
+    private getUniquePrefix(): string {
+        return `${this.prefix + this.idGeneratorService.generate(10)}:`;
+    }
+
+    /**
+     * This method returns the id part of the element id
+     * @param elementId
+     */
+    public extractUniquePrefix(elementId: string): string {
+        const lastSlashIndex = elementId.lastIndexOf(':');
+        return elementId.substring(0, lastSlashIndex + 1);
+    }
+
+    public getPrefix() {
+        return this.prefix;
     }
 }
diff --git a/ui/src/app/connect/services/transformation-rule.service.ts 
b/ui/src/app/connect/services/transformation-rule.service.ts
index f6eaf0823c..020aa57310 100644
--- a/ui/src/app/connect/services/transformation-rule.service.ts
+++ b/ui/src/app/connect/services/transformation-rule.service.ts
@@ -81,22 +81,9 @@ export class TransformationRuleService {
                 targetSchema.eventProperties,
             );
             for (const ep of staticValueProperties) {
-                originalSchema.eventProperties.push(ep);
-                const rule: AddValueTransformationRuleDescription =
-                    new AddValueTransformationRuleDescription();
-                rule['@class'] =
-                    
'org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription';
-                rule.runtimeKey = ep.runtimeName;
-                rule.datatype = ep.runtimeType;
-                rule.label = ep.label;
-                rule.description = ep.description;
-                rule.propertyScope = ep.propertyScope as PropertyScope;
-                rule.semanticType = ep.semanticType;
-                rule.measurementUnit = ep.measurementUnit;
-                rule.staticValue =
-                    this.staticValueTransformService.getStaticValue(
-                        ep.elementId,
-                    );
+                this.pushCopyToOriginalSchemaIfNotExists(originalSchema, ep);
+
+                const rule = this.createAddValueTransformationRule(ep);
                 transformationRuleDescriptions.push(rule);
             }
 
@@ -163,6 +150,56 @@ export class TransformationRuleService {
         }
     }
 
+    private createAddValueTransformationRule(
+        ep: EventPropertyPrimitive,
+    ): AddValueTransformationRuleDescription {
+        const rule: AddValueTransformationRuleDescription =
+            new AddValueTransformationRuleDescription();
+        rule['@class'] =
+            
'org.apache.streampipes.model.connect.rules.value.AddValueTransformationRuleDescription';
+        rule.runtimeKey = ep.runtimeName;
+        rule.datatype = ep.runtimeType;
+        rule.label = ep.label;
+        rule.description = ep.description;
+        rule.propertyScope = ep.propertyScope as PropertyScope;
+        rule.semanticType = ep.semanticType;
+        rule.measurementUnit = ep.measurementUnit;
+        rule.staticValue = this.staticValueTransformService.getStaticValue(
+            ep.elementId,
+        );
+        return rule;
+    }
+
+    /**
+     * Adds a deep copy of the given `EventPropertyPrimitive` to the
+     * `originalSchema` if it does not already exist.
+     * If a property with the same unique prefix (excluding the suffix
+     * representing the ID) exists, only the element ID is updated.
+     */
+    private pushCopyToOriginalSchemaIfNotExists(
+        originalSchema: EventSchema,
+        ep: EventPropertyPrimitive,
+    ): void {
+        const uniquePrefix =
+            this.staticValueTransformService.extractUniquePrefix(ep.elementId);
+
+        const existingProperty = originalSchema.eventProperties.find(
+            property =>
+                this.staticValueTransformService.extractUniquePrefix(
+                    property.elementId,
+                ) === uniquePrefix,
+        );
+
+        if (existingProperty) {
+            existingProperty.elementId = ep.elementId;
+        } else {
+            const epCopy: EventPropertyPrimitive = JSON.parse(
+                JSON.stringify(ep),
+            );
+            originalSchema.eventProperties.push(epCopy);
+        }
+    }
+
     public getMoveRules(
         newEventProperties: EventProperty[],
         oldEventSchema: EventSchema,
@@ -310,12 +347,15 @@ export class TransformationRuleService {
     ): DeleteRuleDescription[] {
         const resultKeys: string[] = [];
 
-        const allNewIds: string[] = this.getAllIds(
+        let allNewIds: string[] = this.getAllIds(
             newEventSchema.eventProperties,
         );
-        const allOldIds: string[] = this.getAllIds(
+        allNewIds = this.transformStaticValueIds(allNewIds);
+
+        let allOldIds: string[] = this.getAllIds(
             oldEventSchema.eventProperties,
         );
+        allOldIds = this.transformStaticValueIds(allOldIds);
 
         for (const id of allOldIds) {
             // if not in new ids create delete rule
@@ -340,6 +380,20 @@ export class TransformationRuleService {
         return resultRules;
     }
 
+    /**
+     * This is required because for the static value enrichment the actual 
value is
+     * encoded in the elementId. Only the prefix is unique and the suffix is 
the value
+     */
+    private transformStaticValueIds(ids: string[]): string[] {
+        const prefix = this.staticValueTransformService.getPrefix();
+        return ids.map(id => {
+            if (id.startsWith(prefix)) {
+                return 
this.staticValueTransformService.extractUniquePrefix(id);
+            }
+            return id;
+        });
+    }
+
     public getUnitTransformRules(
         newEventProperties: EventProperty[],
         oldEventSchema: EventSchema,

Reply via email to