Repository: apache/streampipes
Pull request #3251 (2024-09-24 20:42:32)

refactor: Rename domain properties to semantic type
<!--
  ~ 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.
  ~
  -->

  <!--
Thanks for contributing! Here are some tips you can follow to help us incorporate your contribution quickly and easily:
1. If this is your first time, please read our contributor guidelines:
    - https://streampipes.apache.org/community/get-involved/
    - https://cwiki.apache.org/confluence/display/STREAMPIPES/Getting+Started
2. Make sure the PR title is formatted like: `[#<GitHub issue id>] PR title ...`
3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., `[WIP][#<GitHub issue id>] PR title ...`.
4. Please write your PR title to summarize what this PR proposes/fixes.
5. Link the PR to the corresponding GitHub issue (if present) in the `Development` section in the right menu bar.
6. Be sure to keep the PR description updated to reflect all changes.
7. If possible, provide a concise example to reproduce the issue for a faster review.
8. Make sure tests pass via `mvn clean install`.
9. (Optional) If the contribution is large, please file an Apache ICLA
    - http://apache.org/licenses/icla.pdf
-->

### Purpose
<!--
Please clarify what changes you are proposing and describe how those changes will address the issue.
Furthermore, describe potential consequences the changes might have.
-->

For better clarity, rename `domainProperties` to `semanticType` in the `EventProperty` model. 
Semantic types are now stored as a string instead of a `List<URI>`. 
Old usages of domainProperties should still work and have been marked as deprecated.
We should also change these in the Python and Go client.

### Remarks
<!--
Is there anything left we need to pay attention on?
Are there some references that might be important? E.g. links to Confluence, or discussions
on the mailing list or GitHub.
-->
PR introduces (a) breaking change(s): no

PR introduces (a) deprecation(s): yes
* Use `semanticType` instead of `domainProperties` to assign a semantic type to event properties.



Patch:
diff --git a/streampipes-client-go/streampipes/model/common.go b/streampipes-client-go/streampipes/model/common.go
index 0cb1d9631f..d5a81d684b 100644
--- a/streampipes-client-go/streampipes/model/common.go
+++ b/streampipes-client-go/streampipes/model/common.go
@@ -29,7 +29,7 @@ type EventProperty struct {
 	Label              string             `json:"label,omitempty"`
 	Description        string             `json:"description,omitempty"`
 	RuntimeName        string             `json:"runtimeName,omitempty"`
-	DomainProperties   []string           `json:"domainProperties,omitempty"`
+	SemanticType       string             `json:"semanticType,omitempty"`
 	PropertyScope      string             `json:"propertyScope,omitempty"`
 	RuntimeID          string             `json:"runtimeId,omitempty"`
 	RuntimeType        string             `json:"runtimeType"`
@@ -42,7 +42,7 @@ type EventProperties struct {
 	Label              string            `json:"label"`
 	Description        string            `json:"description"`
 	RuntimeName        string            `json:"runtimeName"`
-	DomainProperties   []string          `json:"domainProperties"`
+	SemanticType       string            `json:"semanticType"`
 	PropertyScope      string            `json:"propertyScope"`
 	RuntimeID          string            `json:"runtimeId"`
 	RuntimeType        string            `json:"runtimeType,omitempty"`
diff --git a/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py b/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
index 6d042088f3..6587a2e53c 100644
--- a/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
+++ b/streampipes-client-python/streampipes/functions/utils/data_stream_generator.py
@@ -78,7 +78,7 @@ def create_data_stream(
             EventProperty(  # type: ignore
                 label="timestamp",
                 runtime_name="timestamp",
-                domain_properties=["http://schema.org/DateTime"],
+                semantic_type="http://schema.org/DateTime",
                 property_scope="HEADER_PROPERTY",
                 runtime_type="http://www.w3.org/2001/XMLSchema#long",
             )
diff --git a/streampipes-client-python/streampipes/model/common.py b/streampipes-client-python/streampipes/model/common.py
index 950bb7f066..afcac4beac 100644
--- a/streampipes-client-python/streampipes/model/common.py
+++ b/streampipes-client-python/streampipes/model/common.py
@@ -109,7 +109,7 @@ class EventProperty(BasicModel):
     label: Optional[StrictStr]
     description: Optional[StrictStr]
     runtime_name: StrictStr
-    domain_properties: Optional[List[StrictStr]] = Field(default_factory=list)
+    semantic_type: Optional[StrictStr]
     property_scope: Optional[StrictStr] = Field(default="MEASUREMENT_PROPERTY")
     runtime_id: Optional[StrictStr]
     runtime_type: StrictStr = Field(default="http://www.w3.org/2001/XMLSchema#string")
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
index f385334d05..7a262fca26 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
@@ -29,9 +29,6 @@ import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
 import org.apache.streampipes.model.template.PipelineTemplateInvocation;
 import org.apache.streampipes.vocabulary.SO;
 
-import java.net.URI;
-import java.util.List;
-
 public class PersistPipelineHandler {
 
   private static final String templateId = "org.apache.streampipes.manager.template.instances.DataLakePipelineTemplate";
@@ -97,16 +94,13 @@ public class PersistPipelineHandler {
         .stream()
         .filter(ep -> ep instanceof EventPropertyPrimitive)
         .map(ep -> (EventPropertyPrimitive) ep)
-        .filter(ep -> hasTimestampType(ep.getDomainProperties()))
+        .filter(ep -> hasTimestampType(ep.getSemanticType()))
         .map(EventProperty::getRuntimeName)
         .findFirst()
         .orElseThrow(() -> new IllegalArgumentException("Could not find timestamp field in schema"));
   }
 
-  private boolean hasTimestampType(List<URI> semanticTypes) {
-    return semanticTypes
-        .stream()
-        .map(URI::toString)
-        .anyMatch(s -> s.equalsIgnoreCase(SO.DATE_TIME));
+  private boolean hasTimestampType(String semanticType) {
+    return SO.DATE_TIME.equalsIgnoreCase(semanticType);
   }
 }
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
index 1650839226..bc2a2ffba0 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/SchemaMetadataEnricher.java
@@ -24,9 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.PropertyScope;
 import org.apache.streampipes.vocabulary.XSD;
 
-import java.net.URI;
-import java.util.List;
-
 public class SchemaMetadataEnricher {
 
   public void enrich(EventProperty property,
@@ -41,7 +38,7 @@ public class SchemaMetadataEnricher {
       property.setDescription(propertyDef.description());
     }
     if (property instanceof EventPropertyPrimitive && propertyDef.semanticType() != null) {
-      property.setDomainProperties(List.of(URI.create(propertyDef.semanticType())));
+      property.setSemanticType(propertyDef.semanticType());
     }
   }
 
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 a7ff90b45c..8e2381d506 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
@@ -125,7 +125,7 @@ public class ToOriginalSchemaConverter implements ITransformationRuleVisitor, Pr
   public void visit(TimestampTranfsformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
     property.setRuntimeType(Datatypes.String.toString());
-    property.setDomainProperties(List.of());
+    property.setSemanticType(null);
   }
 
   @Override
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 92b1674d0d..8ea159406f 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
@@ -127,7 +127,7 @@ public class ToTransformedSchemaConverter implements ITransformationRuleVisitor,
     property.setPropertyScope(rule.getPropertyScope().name());
 
     if (Objects.nonNull(rule.getSemanticType())) {
-      property.setDomainProperties(List.of(URI.create(rule.getSemanticType())));
+      property.setSemanticType(rule.getSemanticType());
     }
     if (Objects.nonNull(rule.getMeasurementUnit())) {
       property.setMeasurementUnit(URI.create(rule.getMeasurementUnit()));
@@ -152,7 +152,7 @@ public class ToTransformedSchemaConverter implements ITransformationRuleVisitor,
   @Override
   public void visit(TimestampTranfsformationRuleDescription rule) {
     var property = findPrimitiveProperty(properties, rule.getRuntimeKey());
-    property.setDomainProperties(List.of(URI.create("http://schema.org/DateTime")));
+    property.setSemanticType("http://schema.org/DateTime");
     property.setRuntimeType(Datatypes.Long.toString());
     property.setPropertyScope(PropertyScope.HEADER_PROPERTY.toString());
     var metadata = property.getAdditionalMetadata();
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
index 59d4719a7d..c7e226c3ed 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/ImageStoreUtils.java
@@ -29,10 +29,7 @@ public class ImageStoreUtils {
 
   public static List<EventProperty> getImageProperties(DataLakeMeasure measure) {
     return measure.getEventSchema().getEventProperties().stream()
-        .filter(eventProperty -> eventProperty.getDomainProperties() != null
-            && !eventProperty.getDomainProperties()
-                             .isEmpty()
-            && eventProperty.getDomainProperties().get(0).toString().equals(SPSensor.IMAGE))
+        .filter(eventProperty -> SPSensor.IMAGE.equalsIgnoreCase(eventProperty.getSemanticType()))
         .collect(Collectors.toList());
   }
 }
diff --git a/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java b/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
index b9bd660f08..2fd8e40f76 100644
--- a/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
+++ b/streampipes-extensions-api/src/main/java/org/apache/streampipes/extensions/api/extractor/IParameterExtractor.java
@@ -60,6 +60,8 @@ public interface IParameterExtractor {
 
   <V> List<V> selectedMultiValues(String internalName, Class<V> targetClass);
 
+  <V> List<V> selectedMultiValuesInternalNames(String internalName, Class<V> targetClass);
+
   <V> List<V> selectedTreeNodesInternalNames(String internalName,
                                              Class<V> targetClass);
 
diff --git a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
index 0405a87ca2..f028ccfd12 100644
--- a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
+++ b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/connect/adapter/parser/json/GeoJsonParser.java
@@ -23,7 +23,6 @@ import org.apache.streampipes.extensions.api.connect.IParserEventHandler;
 import org.apache.streampipes.extensions.management.connect.adapter.parser.util.JsonEventProperty;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
 import org.apache.streampipes.model.schema.EventProperty;
-import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.sdk.builder.adapter.GuessSchemaBuilder;
 import org.apache.streampipes.vocabulary.Geo;
 import org.apache.streampipes.vocabulary.SO;
@@ -41,9 +40,6 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -147,12 +143,8 @@ public class GeoJsonParser extends JsonParser {
 
   private EventProperty getEventPropertyGeoJson(String name, Object value, String domain) {
     EventProperty eventProperty = JsonEventProperty.getEventProperty(name, value);
-    try {
-      ((EventPropertyPrimitive) eventProperty).setDomainProperties(Arrays.asList(new URI(domain)));
+    eventProperty.setSemanticType(domain);
 
-    } catch (URISyntaxException e) {
-      LOG.error(e.getMessage());
-    }
     return eventProperty;
   }
 
diff --git a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
index f0a7020447..0f9a46b210 100644
--- a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
+++ b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/util/EventSchemaUtils.java
@@ -24,7 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.vocabulary.SO;
 
-import java.net.URI;
 import java.util.List;
 import java.util.Optional;
 
@@ -47,7 +46,7 @@ public class EventSchemaUtils {
 
   private static Optional<EventPropertyPrimitive> getTimstampProperty(List<EventProperty> eventProperties) {
     for (EventProperty ep : eventProperties) {
-      if (ep instanceof EventPropertyPrimitive && ep.getDomainProperties().contains(URI.create(SO.DATE_TIME))) {
+      if (ep instanceof EventPropertyPrimitive && SO.DATE_TIME.equalsIgnoreCase(ep.getSemanticType())) {
         return Optional.of((EventPropertyPrimitive) ep);
       }
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
index ed0d256605..a5a42a4c09 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/FileReplayAdapter.java
@@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executors;
@@ -212,9 +211,7 @@ public class FileReplayAdapter implements StreamPipesAdapter {
         .getEventSchema()
         .getEventProperties()
         .stream()
-        .filter(eventProperty ->
-                    eventProperty.getDomainProperties()
-                                 .contains(URI.create(SO.DATE_TIME)))
+        .filter(eventProperty -> SO.DATE_TIME.equals(eventProperty.getSemanticType()))
         .findFirst();
 
     if (timestampField.isEmpty()) {
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
index 88a08a6d94..ed49af0e31 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/protocol/stream/HttpServerProtocol.java
@@ -51,9 +51,7 @@ import org.apache.streampipes.sdk.utils.Datatypes;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.ArrayList;
-import java.util.Collections;
 
 public class HttpServerProtocol implements StreamPipesAdapter {
 
@@ -86,8 +84,7 @@ public class HttpServerProtocol implements StreamPipesAdapter {
     primitive.setRuntimeName(memberExtractor.singleValueParameter(EP_RUNTIME_NAME, String.class));
     primitive.setRuntimeType(extractRuntimeType(memberExtractor.selectedSingleValue(EP_RUNTIME_TYPE, String.class)));
     primitive
-        .setDomainProperties(Collections
-            .singletonList(URI.create(memberExtractor.singleValueParameter(EP_DOMAIN_PROPERTY, String.class))));
+        .setSemanticType(memberExtractor.singleValueParameter(EP_DOMAIN_PROPERTY, String.class));
     return primitive;
   }
 
diff --git a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
index 6d908bd7dc..11cb6bfb98 100644
--- a/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
+++ b/streampipes-extensions/streampipes-processors-filters-siddhi/src/main/java/org/apache/streampipes/processors/siddhi/listcollector/ListCollector.java
@@ -83,16 +83,16 @@ public class ListCollector extends StreamPipesSiddhiProcessor
     List<EventProperty> selectedProperty = extractor
         .getInputStreamEventPropertySubset(Collections.singletonList(propertySelector));
 
-    if (selectedProperty.size() > 0) {
+    if (!selectedProperty.isEmpty()) {
       EventPropertyPrimitive prop = (EventPropertyPrimitive) selectedProperty.get(0);
       String newPropertyName = prop.getRuntimeName() + "_list";
       String newDatatype = prop.getRuntimeType();
-      String newDomainProperty = prop.getDomainProperties().get(0).toString();
+      String newSemanticType = prop.getSemanticType();
 
       EventPropertyList ep = EpProperties.listEp(Labels.from("list", "", ""),
           newPropertyName,
           Datatypes.fromDatatypeString(newDatatype),
-          newDomainProperty);
+          newSemanticType);
 
       inputSchema.addEventProperty(ep);
     }
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
index 05c02730ee..17ed2b9c87 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
@@ -26,7 +26,6 @@ import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticPro
 import org.apache.streampipes.sdk.utils.Datatypes;
 import org.apache.streampipes.vocabulary.SO;
 
-import java.net.URI;
 import java.util.List;
 
 public class DataLakeDimensionProvider {
@@ -50,7 +49,7 @@ public class DataLakeDimensionProvider {
 
   private boolean satisfiesFilter(EventPropertyPrimitive field) {
     return !field.getRuntimeType().equals(Datatypes.Float.toString())
-        &&  !(field.getDomainProperties().stream().map(URI::toString).toList().contains(SO.DATE_TIME));
+        &&  !(SO.DATE_TIME.equalsIgnoreCase(field.getSemanticType()));
   }
 
   private void addFieldIfNotExists(EventPropertyPrimitive field,
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
index 225a899533..225fe1180d 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultType.java
@@ -22,8 +22,8 @@ public enum MatchingResultType {
 
   DATATYPE_MATCH("Datatype Match", "A required datatype is not present in the input event property."),
   STREAM_MATCH("Stream Match", ""),
-  DOMAIN_PROPERTY_MATCH("Domain Property Match",
-      "A required domain property is not present in the input event property."),
+  SEMANTIC_TYPE_MATCH("Semantic Type Match",
+      "A required semantic type is not present in the input event property."),
   FORMAT_MATCH("Format Match", "No supported transport format found."),
   GROUNDING_MATCH("Grounding Match", ""),
   PROTOCOL_MATCH("Protocol Match", "No supported communication protocol found."),
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
index 2bfc4ce28d..ceddacc02b 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventProperty.java
@@ -19,15 +19,11 @@
 package org.apache.streampipes.model.schema;
 
 import org.apache.streampipes.model.util.ElementIdGenerator;
-import org.apache.streampipes.model.util.ListUtils;
 
 import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
-import java.net.URI;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -45,15 +41,13 @@ public abstract class EventProperty {
   private String label;
   private String description;
   private String runtimeName;
-  private List<URI> domainProperties;
+  private String semanticType;
   private String propertyScope;
   private String runtimeId;
   private Map<String, Object> additionalMetadata;
 
-
   public EventProperty() {
     this.elementId = ElementIdGenerator.makeElementId(EventProperty.class);
-    this.domainProperties = new ArrayList<>();
     this.additionalMetadata = new HashMap<>();
   }
 
@@ -62,21 +56,16 @@ public abstract class EventProperty {
     this.label = other.getLabel();
     this.description = other.getDescription();
     this.runtimeName = other.getRuntimeName();
-    this.domainProperties = other.getDomainProperties();
     this.propertyScope = other.getPropertyScope();
     this.runtimeId = other.getRuntimeId();
     this.additionalMetadata = other.getAdditionalMetadata();
+    this.semanticType = other.getSemanticType();
   }
 
-  public EventProperty(List<URI> subClassOf) {
-    this();
-    this.domainProperties = subClassOf;
-  }
-
-  public EventProperty(String propertyName, List<URI> subClassOf) {
+  public EventProperty(String propertyName, String semanticType) {
     this();
     this.runtimeName = propertyName;
-    this.domainProperties = subClassOf;
+    this.semanticType = semanticType;
   }
 
   public EventProperty(String propertyName) {
@@ -97,14 +86,6 @@ public abstract class EventProperty {
     this.runtimeName = propertyName;
   }
 
-  public List<URI> getDomainProperties() {
-    return domainProperties;
-  }
-
-  public void setDomainProperties(List<URI> subClassOf) {
-    this.domainProperties = subClassOf;
-  }
-
   public String getLabel() {
     return label;
   }
@@ -153,9 +134,17 @@ public abstract class EventProperty {
     this.additionalMetadata = additionalMetadata;
   }
 
+  public String getSemanticType() {
+    return semanticType;
+  }
+
+  public void setSemanticType(String semanticType) {
+    this.semanticType = semanticType;
+  }
+
   @Override
   public int hashCode() {
-    return Objects.hash(elementId, label, description, runtimeName, domainProperties, propertyScope,
+    return Objects.hash(elementId, label, description, runtimeName, semanticType, propertyScope,
         runtimeId);
   }
 
@@ -174,7 +163,7 @@ public abstract class EventProperty {
            && Objects.equals(runtimeName, that.runtimeName)
            && Objects.equals(propertyScope, that.propertyScope)
            && Objects.equals(runtimeId, that.runtimeId)
-           && ListUtils.isEqualList(this.domainProperties, that.domainProperties);
+           && Objects.equals(semanticType, that.semanticType);
   }
 
   @Override
@@ -184,7 +173,7 @@ public abstract class EventProperty {
            + ", label='" + label + '\''
            + ", description='" + description + '\''
            + ", runtimeName='" + runtimeName + '\''
-           + ", domainProperties=" + domainProperties
+           + ", semanticType=" + semanticType
            + ", propertyScope='" + propertyScope + '\''
            + ", runtimeId='" + runtimeId + '\''
            + '}';
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
index 799a6ee568..98af25f1d1 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyList.java
@@ -20,8 +20,6 @@ package org.apache.streampipes.model.schema;
 
 import org.apache.streampipes.model.util.Cloner;
 
-import java.net.URI;
-import java.util.List;
 import java.util.Objects;
 
 public class EventPropertyList extends EventProperty {
@@ -51,10 +49,9 @@ public class EventPropertyList extends EventProperty {
     this.eventProperty = listProperty;
   }
 
-  public EventPropertyList(String propertyName, EventProperty eventProperty, List<URI> domainProperties) {
-    super(propertyName);
+  public EventPropertyList(String propertyName, EventProperty eventProperty, String semanticType) {
+    super(propertyName, semanticType);
     this.eventProperty = eventProperty;
-    this.setDomainProperties(domainProperties);
   }
 
   public EventProperty getEventProperty() {
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
index e1fa7d40cb..0822c163a4 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/schema/EventPropertyPrimitive.java
@@ -21,7 +21,6 @@ package org.apache.streampipes.model.schema;
 import org.apache.streampipes.model.util.Cloner;
 
 import java.net.URI;
-import java.util.List;
 import java.util.Objects;
 
 public class EventPropertyPrimitive extends EventProperty {
@@ -44,13 +43,11 @@ public class EventPropertyPrimitive extends EventProperty {
     }
   }
 
-  public EventPropertyPrimitive(List<URI> subClassOf) {
-    super(subClassOf);
-  }
-
-  public EventPropertyPrimitive(String runtimeType, String runtimeName,
-                                String measurementUnit, List<URI> subClassOf) {
-    super(runtimeName, subClassOf);
+  public EventPropertyPrimitive(String runtimeType,
+                                String runtimeName,
+                                String measurementUnit,
+                                String semanticType) {
+    super(runtimeName, semanticType);
     this.runtimeType = runtimeType;
     //this.measurementUnit = measurementUnit;
   }
@@ -92,8 +89,8 @@ public class EventPropertyPrimitive extends EventProperty {
     }
     EventPropertyPrimitive that = (EventPropertyPrimitive) o;
     return Objects.equals(runtimeType, that.runtimeType)
-           && Objects.equals(measurementUnit, that.measurementUnit)
-           && Objects.equals(valueSpecification, that.valueSpecification);
+        && Objects.equals(measurementUnit, that.measurementUnit)
+        && Objects.equals(valueSpecification, that.valueSpecification);
   }
 
   @Override
@@ -104,9 +101,9 @@ public class EventPropertyPrimitive extends EventProperty {
   @Override
   public String toString() {
     return "EventPropertyPrimitive{"
-           + "runtimeType='" + runtimeType + '\''
-           + ", measurementUnit=" + measurementUnit
-           + ", valueSpecification=" + valueSpecification
-           + '}';
+        + "runtimeType='" + runtimeType + '\''
+        + ", measurementUnit=" + measurementUnit
+        + ", valueSpecification=" + valueSpecification
+        + '}';
   }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
index 4106f664da..90a0fdbcc8 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/PropertyDuplicateRemover.java
@@ -43,29 +43,25 @@ public class PropertyDuplicateRemover {
       int i = 1;
       EventProperty newProperty = p;
       while (isAlreadyDefined(existingProperties, newProperty)) {
-        if (newProperty instanceof EventPropertyPrimitive) {
-          EventPropertyPrimitive primitive = (EventPropertyPrimitive) newProperty;
+        if (newProperty instanceof EventPropertyPrimitive primitive) {
           newProperty = new EventPropertyPrimitive(primitive.getRuntimeType(), primitive.getRuntimeName() + i, "",
-              primitive.getDomainProperties());
+              primitive.getSemanticType());
         }
-        if (newProperty instanceof EventPropertyNested) {
-          EventPropertyNested nested = (EventPropertyNested) newProperty;
+        if (newProperty instanceof EventPropertyNested nested) {
 
           //TODO: hack
           List<EventProperty> nestedProperties = new ArrayList<>();
 
           for (EventProperty np : nested.getEventProperties()) {
-            if (np instanceof EventPropertyPrimitive) {
-              EventPropertyPrimitive thisPrimitive = (EventPropertyPrimitive) np;
+            if (np instanceof EventPropertyPrimitive thisPrimitive) {
               EventProperty newNested =
                   new EventPropertyPrimitive(thisPrimitive.getRuntimeType(), thisPrimitive.getRuntimeName(), "",
-                      thisPrimitive.getDomainProperties());
+                      thisPrimitive.getSemanticType());
               nestedProperties.add(newNested);
             }
 
           }
           newProperty = new EventPropertyNested(nested.getRuntimeName() + i, nestedProperties);
-          //newProperty = new EventPropertyNested(nested.getPropertyName() +i, nested.getEventProperties());
         }
         i++;
       }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
index 656d10a4a7..902df7dc7d 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/TransformOutputSchemaGenerator.java
@@ -36,7 +36,6 @@ import org.apache.streampipes.model.util.Cloner;
 import org.apache.streampipes.sdk.helpers.Tuple2;
 
 import java.net.URI;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -158,7 +157,7 @@ public class TransformOutputSchemaGenerator extends OutputSchemaGenerator<Transf
       }
 
     } else if (transformOperationType == TransformOperationType.DOMAIN_PROPERTY_TRANSFORMATION) {
-      eventProperty.setDomainProperties(Collections.singletonList(URI.create(value)));
+      eventProperty.setSemanticType(value);
 
     } else if (transformOperationType == TransformOperationType.RUNTIME_NAME_TRANSFORMATION) {
       eventProperty.setRuntimeName(value);
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
index a27f1350cd..6f9f121e2e 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatch.java
@@ -30,14 +30,14 @@ public class ListPropertyMatch implements Matcher<EventPropertyList, EventProper
     if (requirement.getEventProperty() == null) {
       return true;
     } else {
-      return domainPropertyMatch(offer, requirement, errorLog) && listItemMatch(offer, requirement,
+      return semanticTypeMatch(offer, requirement, errorLog) && listItemMatch(offer, requirement,
           errorLog);
     }
   }
 
-  private boolean domainPropertyMatch(EventPropertyList offer, EventPropertyList requirement,
+  private boolean semanticTypeMatch(EventPropertyList offer, EventPropertyList requirement,
                                       List<MatchingResultMessage> errorLog) {
-    return new DomainPropertyMatch().match(offer.getDomainProperties(), requirement.getDomainProperties(),
+    return new SemanticTypeMatch().match(offer.getSemanticType(), requirement.getSemanticType(),
         errorLog);
   }
 
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
index 82fa379c96..45124c0a57 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PrimitivePropertyMatch.java
@@ -38,16 +38,16 @@ public class PrimitivePropertyMatch extends AbstractMatcher<EventPropertyPrimiti
 
     boolean matchesUnit = unitMatch(offer.getMeasurementUnit(), requirement.getMeasurementUnit(), errorLog);
     boolean matchesDatatype = datatypeMatch(offer.getRuntimeType(), requirement.getRuntimeType(), errorLog);
-    boolean matchesDomainProperty = domainPropertyMatch(offer.getDomainProperties(), requirement.getDomainProperties
-        (), errorLog);
+    boolean matchesSemanticType = semanticTypeMatch(offer.getSemanticType(), requirement.getSemanticType(), errorLog);
 
     return MatchingUtils.nullCheck(offer, requirement)
-        || (matchesUnit && matchesDatatype && matchesDomainProperty);
+        || (matchesUnit && matchesDatatype && matchesSemanticType);
   }
 
-  private boolean domainPropertyMatch(List<URI> offer,
-                                      List<URI> requirement, List<MatchingResultMessage> errorLog) {
-    return new DomainPropertyMatch().match(offer, requirement, errorLog);
+  private boolean semanticTypeMatch(String offer,
+                                    String requirement,
+                                    List<MatchingResultMessage> errorLog) {
+    return new SemanticTypeMatch().match(offer, requirement, errorLog);
   }
 
   private boolean datatypeMatch(String offer, String requirement,
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
index ebbd28561e..ed0d4ec13f 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/PropertyMatch.java
@@ -59,7 +59,7 @@ public class PropertyMatch extends AbstractMatcher<EventProperty, EventProperty>
 
   private boolean isAnyProperty(EventProperty eventProperty) {
     return eventProperty instanceof EventPropertyPrimitive
-        && eventProperty.getDomainProperties() == null
+        && eventProperty.getSemanticType() == null
         && ((EventPropertyPrimitive) eventProperty).getMeasurementUnit() == null
         && ((EventPropertyPrimitive) eventProperty).getRuntimeType() == null;
   }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
similarity index 62%
rename from streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java
rename to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
index ce2518d2e2..d748e9fc63 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/DomainPropertyMatch.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/SemanticTypeMatch.java
@@ -22,22 +22,21 @@ import org.apache.streampipes.manager.matching.v2.utils.MatchingUtils;
 import org.apache.streampipes.model.client.matching.MatchingResultMessage;
 import org.apache.streampipes.model.client.matching.MatchingResultType;
 
-import java.net.URI;
 import java.util.List;
+import java.util.Objects;
 
-public class DomainPropertyMatch extends AbstractMatcher<List<URI>, List<URI>> {
+public class SemanticTypeMatch extends AbstractMatcher<String, String> {
 
-  public DomainPropertyMatch() {
-    super(MatchingResultType.DOMAIN_PROPERTY_MATCH);
+  public SemanticTypeMatch() {
+    super(MatchingResultType.SEMANTIC_TYPE_MATCH);
   }
 
   @Override
-  public boolean match(List<URI> offer, List<URI> requirement, List<MatchingResultMessage> errorLog) {
-    if (offer == null && ((requirement != null) && requirement.size() > 0)) {
+  public boolean match(String offer, String requirement, List<MatchingResultMessage> errorLog) {
+    if (offer == null && (requirement != null)) {
       return false;
     }
-    boolean match = MatchingUtils.nullCheck(offer, requirement)
-        || requirement.stream().allMatch(req -> offer.stream().anyMatch(of -> req.toString().equals(of.toString())));
+    boolean match = MatchingUtils.nullCheck(offer, requirement) || requirement.equalsIgnoreCase(offer);
 
     if (!match) {
       buildErrorMessage(errorLog, buildText(requirement));
@@ -45,12 +44,8 @@ public class DomainPropertyMatch extends AbstractMatcher<List<URI>, List<URI>> {
     return match;
   }
 
-  private String buildText(List<URI> requirement) {
-    if (requirement == null || requirement.size() == 0) {
-      return "-";
-    } else {
-      return requirement.get(0).toString();
-    }
+  private String buildText(String requirement) {
+    return Objects.requireNonNullElse(requirement, "-");
   }
 
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
index 16acbba678..eb212bb33e 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/remote/ContainerProvidedOptionsHandler.java
@@ -30,6 +30,7 @@ import com.google.gson.JsonSyntaxException;
 import org.apache.http.client.fluent.Response;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 public class ContainerProvidedOptionsHandler {
 
@@ -49,7 +50,7 @@ public class ContainerProvidedOptionsHandler {
   }
 
   private RuntimeOptionsResponse handleResponse(Response httpResp) throws JsonSyntaxException, IOException {
-    String resp = httpResp.returnContent().asString();
+    String resp = httpResp.returnContent().asString(StandardCharsets.UTF_8);
     return JacksonSerializer.getObjectMapper().readValue(resp, RuntimeOptionsResponse.class);
   }
 
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
index 2ad5f735e5..1793698efb 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
@@ -19,6 +19,7 @@
 package org.apache.streampipes.sdk;
 
 import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
 import org.apache.streampipes.model.staticproperty.CodeInputStaticProperty;
 import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
 import org.apache.streampipes.model.staticproperty.FileStaticProperty;
@@ -97,9 +98,9 @@ public class StaticProperties {
    * @return A configured FreeTextStaticProperty instance.
    */
   public static FreeTextStaticProperty stringFreeTextProperty(
-          Label label,
-          boolean isMultiLine,
-          boolean arePlaceholdersSupported) {
+      Label label,
+      boolean isMultiLine,
+      boolean arePlaceholdersSupported) {
     var property = stringFreeTextProperty(label);
     property.setMultiLine(isMultiLine);
     property.setPlaceholdersSupported(arePlaceholdersSupported);
@@ -233,6 +234,17 @@ public class StaticProperties {
     return osp;
   }
 
+  public static AnyStaticProperty multiValueSelection(Label label, List<Option> options) {
+    var osp = new AnyStaticProperty(
+        label.getInternalId(),
+        label.getLabel(),
+        label.getDescription()
+    );
+    osp.setOptions(options);
+
+    return osp;
+  }
+
   public static SecretStaticProperty secretValue(Label label) {
     return new SecretStaticProperty(label.getInternalId(),
         label.getLabel(), label.getDescription());
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
index cdfaea0395..d313fe301d 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PrimitivePropertyBuilder.java
@@ -25,7 +25,6 @@ import org.apache.streampipes.model.schema.QuantitativeValue;
 import org.apache.streampipes.sdk.utils.Datatypes;
 
 import java.net.URI;
-import java.util.Collections;
 import java.util.List;
 
 public class PrimitivePropertyBuilder {
@@ -53,12 +52,26 @@ public class PrimitivePropertyBuilder {
   /**
    * Specifies the semantics of the property (e.g., whether a double value stands for a latitude coordinate).
    *
-   * @param domainProperty The domain property as a String. The domain property should reflect an URI. Use some
+   * @param semanticType The semantic type as a String. Use some
    *                       existing vocabulary from {@link org.apache.streampipes.vocabulary} or create your own.
-   * @return
+   * @return PrimitivePropertyBuilder
+   */
+  public PrimitivePropertyBuilder semanticType(String semanticType) {
+    this.eventProperty.setSemanticType(semanticType);
+    return this;
+  }
+
+  /**
+   * @deprecated use {@link PrimitivePropertyBuilder#semanticType(String)} instead.
+   * Specifies the semantics of the property (e.g., whether a double value stands for a latitude coordinate).
+   *
+   * @param semanticType The semantic type as a String. Use some
+   *                       existing vocabulary from {@link org.apache.streampipes.vocabulary} or create your own.
+   * @return PrimitivePropertyBuilder
    */
-  public PrimitivePropertyBuilder domainProperty(String domainProperty) {
-    this.eventProperty.setDomainProperties(Collections.singletonList(URI.create(domainProperty)));
+  @Deprecated(forRemoval = true, since = "0.97.0")
+  public PrimitivePropertyBuilder domainProperty(String semanticType) {
+    this.eventProperty.setSemanticType(semanticType);
     return this;
   }
 
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
index fed9a70db4..eecb6fbec0 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/PropertyRequirementsBuilder.java
@@ -22,8 +22,6 @@ import org.apache.streampipes.sdk.utils.Datatypes;
 import org.apache.streampipes.vocabulary.StreamPipes;
 
 import java.net.URI;
-import java.util.Arrays;
-import java.util.stream.Collectors;
 
 public class PropertyRequirementsBuilder {
 
@@ -57,15 +55,6 @@ public class PropertyRequirementsBuilder {
     return this;
   }
 
-  public PropertyRequirementsBuilder domainPropertyReq(String... domainProperties) {
-    this.propertyReq.setDomainProperties(Arrays
-        .stream(domainProperties)
-        .map(URI::create)
-        .collect(Collectors.toList()));
-
-    return this;
-  }
-
   public PropertyRequirementsBuilder measurementUnitReq(String measurementUnit) {
     this.propertyReq.setMeasurementUnit(URI.create(measurementUnit));
     return this;
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
index bb365ec3c3..844f26af2c 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/extractor/AbstractParameterExtractor.java
@@ -62,7 +62,7 @@ public abstract class AbstractParameterExtractor<T extends InvocableStreamPipesE
     implements IParameterExtractor {
 
   protected T sepaElement;
-  private TypeParser typeParser;
+  private final TypeParser typeParser;
 
   public AbstractParameterExtractor(T sepaElement) {
     this.sepaElement = sepaElement;
@@ -246,6 +246,17 @@ public abstract class AbstractParameterExtractor<T extends InvocableStreamPipesE
         .collect(Collectors.toList());
   }
 
+  @Override
+  public <V> List<V> selectedMultiValuesInternalNames(String internalName, Class<V> targetClass) {
+    return getStaticPropertyByName(internalName, AnyStaticProperty.class)
+        .getOptions()
+        .stream()
+        .filter(Option::isSelected)
+        .map(Option::getInternalName)
+        .map(o -> typeParser.parse(o, targetClass))
+        .collect(Collectors.toList());
+  }
+
   @Override
   /**
    * Extracts the user configuration from the tree static property.
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
index ced0dd00e9..a17247a2f3 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpProperties.java
@@ -18,7 +18,6 @@
 
 package org.apache.streampipes.sdk.helpers;
 
-import org.apache.streampipes.commons.Utils;
 import org.apache.streampipes.model.schema.Enumeration;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyList;
@@ -58,9 +57,9 @@ public class EpProperties {
   }
 
   public static EventPropertyList listNestedEp(Label label, String runtimeName, String
-      domainProperty, List<EventProperty> listItemProperties) {
+      semanticType, List<EventProperty> listItemProperties) {
     EventPropertyList list = listNestedEp(label, runtimeName, listItemProperties);
-    list.setDomainProperties(Arrays.asList(URI.create(domainProperty)));
+    list.setSemanticType(semanticType);
     return list;
   }
 
@@ -190,9 +189,8 @@ public class EpProperties {
    * @return {@link org.apache.streampipes.model.schema.EventPropertyList}
    */
   public static EventPropertyList listEp(Label label, String runtimeName, EventProperty eventProperty,
-                                         String domainProperty) {
-    return getPreparedProperty(label, new EventPropertyList(runtimeName, eventProperty, Utils.createURI
-        (domainProperty)));
+                                         String semanticType) {
+    return getPreparedProperty(label, new EventPropertyList(runtimeName, eventProperty, semanticType));
   }
 
   /**
@@ -287,25 +285,26 @@ public class EpProperties {
    * Creates a new primitive property of type integer and the provided domain property.
    *
    * @param runtimeName    The field identifier of the event property at runtime.
-   * @param domainProperty The semantics of the list property as a String. The string should correspond to a URI
-   *                       provided by a vocabulary. Use one of the vocabularies provided in
+   * @param semanticType The semantics of the list property as a String. Use one of the vocabularies provided in
    *                       {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
-  public static EventPropertyPrimitive integerEp(Label label, String runtimeName, String domainProperty) {
-    return ep(label, XSD.INTEGER.toString(), runtimeName, domainProperty);
+  public static EventPropertyPrimitive integerEp(Label label, String runtimeName, String semanticType) {
+    return ep(label, XSD.INTEGER.toString(), runtimeName, semanticType);
   }
 
   /**
    * Creates a new primitive property of type integer and the provided domain properties. In addition, the value range
    * of the property is restricted to the defined {@link org.apache.streampipes.model.schema.Enumeration}
    *
+   * @deprecated provide the semantic type as string
    * @param runtimeName      The field identifier of the event property at runtime.
    * @param domainProperties The semantics of the list property as a list of URIs. Use one of the vocabularies
    *                         provided in
    *                         {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive integerEp(Label label, String runtimeName, List<URI> domainProperties) {
     return ep(label, XSD.INTEGER.toString(), runtimeName, domainProperties);
   }
@@ -317,15 +316,15 @@ public class EpProperties {
    *                       If you do not want to have a label besides the runtime name, use
    *                       {@link org.apache.streampipes.sdk.helpers.Labels}
    * @param runtimeName    The field identifier of the event property at runtime.
-   * @param domainProperty The semantics of the list property as a String. The string should correspond to a URI
-   *                       provided by a vocabulary. Use one of the vocabularies provided in
+   * @param semanticType The semantics of the list property as a String. Use one of the vocabularies provided in
    *                       {@link org.apache.streampipes.vocabulary} or create your own domain-specific vocabulary.
    * @return {@link org.apache.streampipes.model.schema.EventPropertyPrimitive}
    */
-  public static EventPropertyPrimitive longEp(Label label, String runtimeName, String domainProperty) {
-    return ep(label, XSD.LONG.toString(), runtimeName, domainProperty);
+  public static EventPropertyPrimitive longEp(Label label, String runtimeName, String semanticType) {
+    return ep(label, XSD.LONG.toString(), runtimeName, semanticType);
   }
 
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive longEp(Label label, String runtimeName, List<URI> domainProperties) {
     return ep(label, XSD.LONG.toString(), runtimeName, domainProperties);
   }
@@ -353,14 +352,18 @@ public class EpProperties {
     return ep;
   }
 
-  public static EventPropertyPrimitive ep(Label label, String runtimeType, String runtimeName, String domainProperty) {
-    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", Utils.createURI
-        (domainProperty)));
+  public static EventPropertyPrimitive ep(Label label,
+                                          String runtimeType,
+                                          String runtimeName,
+                                          String semanticType) {
+    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", semanticType));
   }
 
+  @Deprecated(forRemoval = true, since = "0.97.0")
   private static EventPropertyPrimitive ep(Label label, String runtimeType, String runtimeName, List<URI>
       domainProperties) {
-    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", domainProperties));
+    String semanticType = domainProperties.isEmpty() ? null : domainProperties.get(0).toString();
+    return getPreparedProperty(label, new EventPropertyPrimitive(runtimeType, runtimeName, "", semanticType));
   }
 
   private static <T extends EventProperty> T getPreparedProperty(Label label, T eventProperty) {
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
index 1d310fcb8e..77afed7fe7 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/EpRequirements.java
@@ -18,7 +18,6 @@
 
 package org.apache.streampipes.sdk.helpers;
 
-import org.apache.streampipes.commons.Utils;
 import org.apache.streampipes.model.schema.EventProperty;
 import org.apache.streampipes.model.schema.EventPropertyList;
 import org.apache.streampipes.model.schema.EventPropertyNested;
@@ -124,28 +123,48 @@ public class EpRequirements {
     return appendDomainProperty(datatypeReq(SO.NUMBER), domainProperty);
   }
 
-  private static <T extends EventProperty> EventProperty domainPropertyReq(String domainProperty,
-                                                                           Class<T> eventProperty) {
+  private static <T extends EventProperty> EventProperty semanticTypeReq(String semanticType,
+                                                                         Class<T> eventProperty) {
     EventProperty ep = null;
     try {
       ep = eventProperty.newInstance();
+      ep.setSemanticType(semanticType);
     } catch (InstantiationException | IllegalAccessException e) {
       e.printStackTrace();
     }
-    ep.setDomainProperties(Utils.createURI(domainProperty));
     return ep;
   }
 
+  public static EventPropertyPrimitive semanticTypeReq(String semanticType) {
+    return (EventPropertyPrimitive) semanticTypeReq(semanticType, EventPropertyPrimitive.class);
+  }
+
+  public static EventPropertyList semanticTypeReqList(String semanticType) {
+    return (EventPropertyList) semanticTypeReq(semanticType, EventPropertyList.class);
+  }
+
+  /**
+   * @param domainProperty the semantic type
+   * @return EventPropertyPrimitive
+   * @deprecated Use {@link EpRequirements#semanticTypeReq(String)} instead
+   */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyPrimitive domainPropertyReq(String domainProperty) {
-    return (EventPropertyPrimitive) domainPropertyReq(domainProperty, EventPropertyPrimitive.class);
+    return (EventPropertyPrimitive) semanticTypeReq(domainProperty, EventPropertyPrimitive.class);
   }
 
+  /**
+   * @param domainProperty the semantic type
+   * @return EventPropertyList
+   * @deprecated Use {@link EpRequirements#semanticTypeReqList(String)} instead
+   */
+  @Deprecated(forRemoval = true, since = "0.97.0")
   public static EventPropertyList domainPropertyReqList(String domainProperty) {
-    return (EventPropertyList) domainPropertyReq(domainProperty, EventPropertyList.class);
+    return (EventPropertyList) semanticTypeReq(domainProperty, EventPropertyList.class);
   }
 
-  private static EventPropertyPrimitive appendDomainProperty(EventPropertyPrimitive property, String domainProperty) {
-    property.setDomainProperties(Utils.createURI(domainProperty));
+  private static EventPropertyPrimitive appendDomainProperty(EventPropertyPrimitive property, String semanticType) {
+    property.setSemanticType(semanticType);
     return property;
   }
 
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java
new file mode 100644
index 0000000000..30e04cd69c
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/serializer/EventPropertySerializer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.storage.couchdb.serializer;
+
+import org.apache.streampipes.model.schema.EventProperty;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+
+import java.lang.reflect.Type;
+
+public class EventPropertySerializer extends CouchDbJsonSerializer<EventProperty> {
+
+  private static final String DomainProperties = "domainProperties";
+
+  @Override
+  public EventProperty deserialize(JsonElement json,
+                                   Type typeOfT,
+                                   JsonDeserializationContext context) throws JsonParseException {
+
+    JsonObject jsonObject = json.getAsJsonObject();
+    String type = jsonObject.get("type").getAsString();
+    JsonElement element = jsonObject.get("properties");
+    if (element.getAsJsonObject().has(DomainProperties)) {
+      var domainProperties = element.getAsJsonObject().get(DomainProperties).getAsJsonArray();
+      if (!domainProperties.isEmpty()) {
+        element.getAsJsonObject().add("semanticType", new JsonPrimitive(domainProperties.get(0).getAsString()));
+      }
+      element.getAsJsonObject().remove(DomainProperties);
+
+    }
+
+    try {
+      return context.deserialize(element, Class.forName(type));
+    } catch (ClassNotFoundException cnfe) {
+      throw new JsonParseException("Unknown element type: " + type, cnfe);
+    }
+  }
+}
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 37a2293ff4..685db7ee03 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
@@ -75,7 +75,7 @@ public class GsonSerializer {
 
   public static GsonBuilder getGsonBuilder() {
     GsonBuilder builder = new GsonBuilder();
-    builder.registerTypeAdapter(EventProperty.class, new CouchDbJsonSerializer<EventProperty>());
+    builder.registerTypeAdapter(EventProperty.class, new EventPropertySerializer());
     builder.registerTypeAdapter(StaticProperty.class, new CouchDbJsonSerializer<StaticProperty>());
     builder.registerTypeAdapter(OutputStrategy.class, new CouchDbJsonSerializer<OutputStrategy>());
     builder.registerTypeAdapter(TransportProtocol.class, new CouchDbJsonSerializer<TransportProtocol>());
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 398a67c5f7..1ae8e4e32d 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
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-09-18 15:50:05.
+// Generated using typescript-generator version 3.2.1263 on 2024-09-30 14:11:40.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -1484,12 +1484,12 @@ export class EventProperty {
         | 'org.apache.streampipes.model.schema.EventPropertyPrimitive';
     'additionalMetadata': { [index: string]: any };
     'description': string;
-    'domainProperties': string[];
     'elementId': string;
     'label': string;
     'propertyScope': string;
     'runtimeId': string;
     'runtimeName': string;
+    'semanticType': string;
 
     static 'fromData'(
         data: EventProperty,
@@ -1504,14 +1504,12 @@ export class EventProperty {
             data.additionalMetadata,
         );
         instance.description = data.description;
-        instance.domainProperties = __getCopyArrayFn(__identity<string>())(
-            data.domainProperties,
-        );
         instance.elementId = data.elementId;
         instance.label = data.label;
         instance.propertyScope = data.propertyScope;
         instance.runtimeId = data.runtimeId;
         instance.runtimeName = data.runtimeName;
+        instance.semanticType = data.semanticType;
         return instance;
     }
 
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts b/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
index e0aff4fb37..e4869422e2 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/types/semantic-type.ts
@@ -42,14 +42,24 @@ export class SemanticType {
     }
 
     public static isTimestamp(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.TIMESTAMP);
+        return this.equalsIgnoreCase(
+            SemanticType.TIMESTAMP,
+            property.semanticType,
+        );
     }
 
     public static isImage(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.IMAGE);
+        return this.equalsIgnoreCase(SemanticType.IMAGE, property.semanticType);
     }
 
     public static isNumber(property: EventProperty): boolean {
-        return property.domainProperties.includes(SemanticType.SO_NUMBER);
+        return this.equalsIgnoreCase(
+            SemanticType.SO_NUMBER,
+            property.semanticType,
+        );
+    }
+
+    public static equalsIgnoreCase(str1: string, str2: string): boolean {
+        return str1?.toLowerCase() === str2?.toLowerCase();
     }
 }
diff --git a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
index 93e776b6ec..59c01ae599 100644
--- a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
+++ b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-property-row/event-property-row.component.ts
@@ -159,10 +159,7 @@ export class EventPropertyRowComponent implements OnInit {
     }
 
     isTimestampProperty(node) {
-        if (
-            node.domainProperties &&
-            node.domainProperties.some(dp => dp === SemanticType.TIMESTAMP)
-        ) {
+        if (node.semanticType !== undefined && SemanticType.isTimestamp(node)) {
             node.runtimeType = DataType.LONG;
             return true;
         } else {
diff --git a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
index 09423c2d32..da1b6c5a54 100644
--- a/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
+++ b/ui/src/app/connect/components/adapter-configuration/schema-editor/event-schema/event-schema.component.ts
@@ -211,7 +211,7 @@ export class EventSchemaComponent implements OnChanges {
 
         eventProperty.runtimeName = runtimeName;
         eventProperty.runtimeType = DataType.STRING;
-        eventProperty.domainProperties = [];
+        eventProperty.semanticType = undefined;
         eventProperty.propertyScope = 'DIMENSION_PROPERTY';
         eventProperty.additionalMetadata = {};
 
@@ -230,7 +230,7 @@ export class EventSchemaComponent implements OnChanges {
         eventProperty.runtimeName = 'timestamp';
         eventProperty.label = 'Timestamp';
         eventProperty.description = 'The current timestamp value';
-        eventProperty.domainProperties = [SemanticType.TIMESTAMP];
+        eventProperty.semanticType = SemanticType.TIMESTAMP;
         eventProperty.propertyScope = 'HEADER_PROPERTY';
         eventProperty.runtimeType = DataType.LONG;
         eventProperty.additionalMetadata = {};
@@ -280,7 +280,7 @@ export class EventSchemaComponent implements OnChanges {
     private checkIfValid(eventSchema: EventSchema): boolean {
         this.timestampPresent = false;
         eventSchema.eventProperties.forEach(p => {
-            if (p.domainProperties.indexOf('http://schema.org/DateTime') > -1) {
+            if (SemanticType.isTimestamp(p)) {
                 this.timestampPresent = true;
             }
         });
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
index 84732adcc3..4b6801488b 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.html
@@ -67,7 +67,7 @@
                     class="dmainProperty"
                     name="domainproperty"
                     id="domainproperty"
-                    [(ngModel)]="cachedProperty.domainProperties[0]"
+                    [(ngModel)]="cachedProperty.semanticType"
                     [matAutocomplete]="st"
                     [disabled]="isTimestampProperty"
                     [matAutocompleteDisabled]="isTimestampProperty"
diff --git a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
index 7c262a8e2f..4644e33e10 100644
--- a/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
+++ b/ui/src/app/connect/dialog/edit-event-property/components/edit-schema-transformation/edit-schema-transformation.component.ts
@@ -28,6 +28,8 @@ import { Observable } from 'rxjs';
 import { ShepherdService } from '../../../../../services/tour/shepherd.service';
 import {
     DataType,
+    EventPropertyPrimitive,
+    EventPropertyUnion,
     SemanticType,
     SemanticTypesRestService,
 } from '@streampipes/platform-services';
@@ -40,7 +42,7 @@ import { Router } from '@angular/router';
 })
 export class EditSchemaTransformationComponent implements OnInit {
     @Input()
-    cachedProperty: any;
+    cachedProperty: EventPropertyUnion;
 
     @Input() isTimestampProperty: boolean;
     @Input() isNestedProperty: boolean;
@@ -79,11 +81,12 @@ export class EditSchemaTransformationComponent implements OnInit {
     editTimestampDomainProperty(checked: boolean) {
         if (checked) {
             this.isTimestampProperty = true;
-            this.cachedProperty.domainProperties = [SemanticType.TIMESTAMP];
+            this.cachedProperty.semanticType = SemanticType.TIMESTAMP;
             this.cachedProperty.propertyScope = 'HEADER_PROPERTY';
-            this.cachedProperty.runtimeType = DataType.LONG;
+            (this.cachedProperty as EventPropertyPrimitive).runtimeType =
+                DataType.LONG;
         } else {
-            this.cachedProperty.domainProperties = [];
+            this.cachedProperty.semanticType = undefined;
             this.cachedProperty.propertyScope = 'MEASUREMENT_PROPERTY';
             this.isTimestampProperty = false;
         }
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 f5b527b7e1..0cff8aefd4 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
@@ -149,9 +149,7 @@ export class EditEventPropertyComponent implements OnInit {
         this.property.description = this.cachedProperty.description;
         this.property.elementId = this.cachedProperty.elementId;
 
-        // remove undefined from domain properties array
-        this.property.domainProperties =
-            this.cachedProperty.domainProperties.filter(n => n);
+        this.property.semanticType = this.cachedProperty.semanticType;
         this.property.runtimeName = this.cachedProperty.runtimeName;
         this.property.propertyScope = this.cachedProperty.propertyScope;
 
diff --git a/ui/src/app/connect/filter/timestamp.pipe.ts b/ui/src/app/connect/filter/timestamp.pipe.ts
index d3bd4b5c43..e863268f70 100644
--- a/ui/src/app/connect/filter/timestamp.pipe.ts
+++ b/ui/src/app/connect/filter/timestamp.pipe.ts
@@ -30,8 +30,6 @@ export class TimestampPipe implements PipeTransform {
     constructor() {}
 
     transform(items: EventPropertyUnion[]): EventPropertyUnion[] {
-        return items.filter(item =>
-            item.domainProperties.some(dp => dp === SemanticType.TIMESTAMP),
-        );
+        return items.filter(item => SemanticType.isTimestamp(item));
     }
 }
diff --git a/ui/src/app/connect/services/transformation-rule.service.ts b/ui/src/app/connect/services/transformation-rule.service.ts
index 2d04eb8876..b79883961a 100644
--- a/ui/src/app/connect/services/transformation-rule.service.ts
+++ b/ui/src/app/connect/services/transformation-rule.service.ts
@@ -89,9 +89,7 @@ export class TransformationRuleService {
                 rule.label = ep.label;
                 rule.description = ep.description;
                 rule.propertyScope = ep.propertyScope as PropertyScope;
-                if (ep.domainProperties.length > 0) {
-                    rule.semanticType = ep.domainProperties[0];
-                }
+                rule.semanticType = ep.semanticType;
                 rule.measurementUnit = ep.measurementUnit;
                 rule.staticValue =
                     this.staticValueTransformService.getStaticValue(
@@ -569,9 +567,7 @@ export class TransformationRuleService {
     }
 
     isTimestampProperty(property: EventPropertyPrimitive) {
-        return property.domainProperties.some(
-            dp => dp === SemanticType.TIMESTAMP,
-        );
+        return SemanticType.isTimestamp(property);
     }
 
     private getDatatypeTransformRules(
diff --git a/ui/src/app/core-ui/static-properties/static-property.component.html b/ui/src/app/core-ui/static-properties/static-property.component.html
index e416735c84..3f43c9bd03 100644
--- a/ui/src/app/core-ui/static-properties/static-property.component.html
+++ b/ui/src/app/core-ui/static-properties/static-property.component.html
@@ -94,6 +94,7 @@
                 [parentForm]="parentForm"
                 [completedStaticProperty]="completedStaticProperty"
                 [adapterId]="adapterId"
+                (updateEmitter)="emitUpdate($event)"
             >
             </sp-app-static-runtime-resolvable-any-input>
 
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
index 4690c0f00c..ac1c4f7e54 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
@@ -17,48 +17,65 @@
   -->
 
 <div id="formWrapper" fxFlex="100" fxLayout="column">
-    <div>
+    <div fxLayout="row" class="mb-10">
+        <button
+            mat-button
+            mat-raised-button
+            color="accent"
+            class="small-button"
+            (click)="selectAll(true)"
+            [disabled]="!showOptions"
+        >
+            <span>Select all</span>
+        </button>
+        <button
+            mat-button
+            mat-raised-button
+            class="mat-basic small-button"
+            (click)="selectAll(false)"
+            [disabled]="!showOptions"
+        >
+            <span>Select none</span>
+        </button>
         <button
             mat-button
             mat-raised-button
             color="accent"
             class="small-button"
             (click)="loadOptionsFromRestApi()"
-            style="margin-right: 10px; margin-left: 10px"
             [disabled]="!showOptions"
         >
             <span>Reload</span>
         </button>
+        <mat-spinner
+            *ngIf="loading"
+            color="accent"
+            [mode]="'indeterminate'"
+            [diameter]="15"
+        ></mat-spinner>
     </div>
-    <div
-        *ngIf="!staticProperty.horizontalRendering"
-        fxLayout="column"
-        style="margin-top: 10px"
-    >
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
         <mat-checkbox
             style="padding-left: 10px"
             color="accent"
             *ngFor="let option of staticProperty.options"
             [(ngModel)]="option.selected"
+            (ngModelChange)="checkEmitUpdate()"
         >
             {{ option.name }}
         </mat-checkbox>
     </div>
-    <div fxLayout="column" *ngIf="!showOptions && !loading" class="mt-10">
+    <div fxLayout="column" *ngIf="!showOptions && !loading" class="mb-10">
         <span>(waiting for input)</span>
     </div>
-    <div fxLayout="column" *ngIf="loading">
-        <mat-spinner
-            color="accent"
-            [mode]="'indeterminate'"
-            [diameter]="20"
-        ></mat-spinner>
-    </div>
 
-    <div *ngIf="staticProperty.horizontalRendering">
+    <div *ngIf="staticProperty.horizontalRendering && showOptions">
         <mat-form-field style="width: 100%" color="accent">
-            <mat-label>{{ staticProperty.label }}</mat-label>
-            <mat-select multiple [(ngModel)]="option.selected">
+            <mat-select
+                multiple
+                [(ngModel)]="selectedOptions"
+                (selectionChange)="onSelectionChange()"
+            >
                 <mat-option
                     *ngFor="let option of staticProperty.options"
                     [value]="option"
@@ -66,7 +83,6 @@
                     {{ option.name }}
                 </mat-option>
             </mat-select>
-            <mat-hint>{{ staticProperty.description }}</mat-hint>
         </mat-form-field>
     </div>
 </div>
diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
index 2fb2ea4da5..6d84538535 100644
--- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
+++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.ts
@@ -18,11 +18,13 @@
 
 import { Component, OnInit } from '@angular/core';
 import {
+    Option,
     RuntimeResolvableAnyStaticProperty,
     StaticPropertyUnion,
 } from '@streampipes/platform-services';
 import { RuntimeResolvableService } from '../static-runtime-resolvable-input/runtime-resolvable.service';
 import { BaseRuntimeResolvableSelectionInput } from '../static-runtime-resolvable-input/base-runtime-resolvable-selection-input';
+import { MatSelectChange } from '@angular/material/select';
 
 @Component({
     selector: 'sp-app-static-runtime-resolvable-any-input',
@@ -33,25 +35,40 @@ export class StaticRuntimeResolvableAnyInputComponent
     extends BaseRuntimeResolvableSelectionInput<RuntimeResolvableAnyStaticProperty>
     implements OnInit
 {
+    selectedOptions: Option[] = [];
+
     constructor(runtimeResolvableService: RuntimeResolvableService) {
         super(runtimeResolvableService);
     }
 
     ngOnInit() {
         super.onInit();
+        this.selectedOptions = this.staticProperty.options.filter(
+            o => o.selected,
+        );
+    }
+
+    selectAll(select: boolean): void {
+        this.staticProperty.options.forEach(o => (o.selected = select));
+        this.selectedOptions = select ? this.staticProperty.options : [];
+        this.emitUpdate(true);
+    }
+
+    onSelectionChange(): void {
+        this.staticProperty.options.forEach(option => {
+            option.selected = this.selectedOptions.includes(option);
+        });
     }
 
-    select(id) {
-        for (const option of this.staticProperty.options) {
-            option.selected = false;
-        }
-        this.staticProperty.options.find(
-            option => option.elementId === id,
-        ).selected = true;
+    checkEmitUpdate(): void {
+        this.emitUpdate(true);
     }
 
     afterOptionsLoaded(staticProperty: RuntimeResolvableAnyStaticProperty) {
         this.staticProperty.options = staticProperty.options;
+        this.selectedOptions = this.staticProperty.options.filter(
+            o => o.selected,
+        );
     }
 
     parse(
diff --git a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
index 54693b732e..768ee61ebb 100644
--- a/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
+++ b/ui/src/app/dashboard/components/widgets/table/table-widget.component.ts
@@ -57,7 +57,7 @@ export class TableWidgetComponent
 
         this.widgetDataConfig.eventSchema.eventProperties.forEach(
             (key, index) => {
-                this.semanticTypes[key.runtimeName] = key.domainProperties[0];
+                this.semanticTypes[key.runtimeName] = key.semanticType;
             },
         );
         this.semanticTypes[BaseStreamPipesWidget.TIMESTAMP_KEY] =
diff --git a/ui/src/app/dashboard/sdk/ep-requirements.ts b/ui/src/app/dashboard/sdk/ep-requirements.ts
index 3196a11ced..58b830c43f 100644
--- a/ui/src/app/dashboard/sdk/ep-requirements.ts
+++ b/ui/src/app/dashboard/sdk/ep-requirements.ts
@@ -104,9 +104,9 @@ export class EpRequirements {
         return listEp;
     }
 
-    static domainPropertyReq(domainProperty: string): EventPropertyPrimitive {
+    static domainPropertyReq(semanticType: string): EventPropertyPrimitive {
         const eventProperty = EpRequirements.ep();
-        eventProperty.domainProperties = [domainProperty];
+        eventProperty.semanticType = semanticType;
         return eventProperty;
     }
 
diff --git a/ui/src/app/dashboard/sdk/matching/domain-property-match.ts b/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
index 3c319f5866..92c9c1f5e7 100644
--- a/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
+++ b/ui/src/app/dashboard/sdk/matching/domain-property-match.ts
@@ -17,22 +17,17 @@
  */
 
 export class DomainPropertyMatch {
-    match(
-        domainPropertyRequirements: string[],
-        domainPropertyOffers: string[],
-    ) {
+    match(domainPropertyRequirement: string, domainPropertyOffer: string) {
         if (
-            domainPropertyRequirements === undefined ||
-            domainPropertyRequirements.length === 0
+            domainPropertyRequirement === undefined ||
+            domainPropertyRequirement === ''
         ) {
             return true;
         } else {
-            if (!domainPropertyOffers) {
+            if (!domainPropertyOffer) {
                 return false;
             } else {
-                return (
-                    domainPropertyRequirements[0] === domainPropertyOffers[0]
-                );
+                return domainPropertyRequirement === domainPropertyOffer;
             }
         }
     }
diff --git a/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts b/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
index dea6f256a3..8ecb8ebe81 100644
--- a/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
+++ b/ui/src/app/dashboard/sdk/matching/primitive-property-match.ts
@@ -29,8 +29,8 @@ export class PrimitivePropertyMatch {
                     offer.runtimeType,
                 ) &&
                 new DomainPropertyMatch().match(
-                    requirement.domainProperties,
-                    offer.domainProperties,
+                    requirement.semanticType,
+                    offer.semanticType,
                 )
             );
         } else {
diff --git a/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts b/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
index 40a9e91309..166ba89413 100644
--- a/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
+++ b/ui/src/app/data-explorer/services/data-explorer-field-provider-service.ts
@@ -113,7 +113,7 @@ export class DataExplorerFieldProviderService {
                 dimension: this.isDimensionProperty(property),
                 numeric: this.isNumber(property) || aggregation === 'COUNT',
                 binary: this.isBoolean(property),
-                semanticTypes: property.domainProperties,
+                semanticTypes: [property.semanticType],
             },
         };
         provider.allFields.push(field);
@@ -156,7 +156,7 @@ export class DataExplorerFieldProviderService {
     }
 
     public isTimestamp(p: EventProperty) {
-        return p.domainProperties.some(dp => dp === SemanticType.TIMESTAMP);
+        return SemanticType.isTimestamp(p);
     }
 
     public getAddedFields(
diff --git a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
index 9c6d61eb2a..1ebc5d00e6 100644
--- a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
+++ b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.html
@@ -75,7 +75,7 @@
             <mat-form-field fxFlex color="accent">
                 <mat-label>Semantic type</mat-label>
                 <input
-                    [(ngModel)]="ep.domainProperties[0]"
+                    [(ngModel)]="ep.semanticType"
                     [disabled]="restrictedEditMode"
                     data-cy="semantic-type"
                     fxFlex
diff --git a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
index 94576ade12..97170d9547 100644
--- a/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
+++ b/ui/src/app/editor/components/output-strategy/user-defined-output/user-defined-output.component.ts
@@ -81,7 +81,7 @@ export class UserDefinedOutputStrategyComponent
         const ep = {} as EventPropertyPrimitive;
         ep['@class'] =
             'org.apache.streampipes.model.schema.EventPropertyPrimitive';
-        ep.domainProperties = [];
+        ep.semanticType = undefined;
         ep.elementId =
             'urn:streampipes.org:spi:eventpropertyprimitive:' +
             this.idGeneratorService.generatePrefixedId();


Test patch:
diff --git a/streampipes-client-python/tests/client/test_endpoint.py b/streampipes-client-python/tests/client/test_endpoint.py
index ccf1a3bee3..5b71d83531 100644
--- a/streampipes-client-python/tests/client/test_endpoint.py
+++ b/streampipes-client-python/tests/client/test_endpoint.py
@@ -53,7 +53,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Density",
                             "description": "Denotes the current density of the fluid",
                             "runtimeName": "density",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -66,7 +66,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Temperature",
                             "description": "Denotes the current temperature in degrees celsius",
                             "runtimeName": "temperature",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -131,7 +131,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Density",
                             "description": "Denotes the current density of the fluid",
                             "runtimeName": "density",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
@@ -144,7 +144,7 @@ class TestStreamPipesEndpoints(TestCase):
                             "label": "Temperature",
                             "description": "Denotes the current temperature in degrees celsius",
                             "runtimeName": "temperature",
-                            "domainProperties": ["http://schema.org/Number"],
+                            "semanticType": "http://schema.org/Number",
                             "propertyScope": "MEASUREMENT_PROPERTY",
                             "runtimeId": None,
                             "runtimeType": "http://www.w3.org/2001/XMLSchema#float",
diff --git a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
index ef123ae80d..56d3203519 100644
--- a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
+++ b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/compact/generator/AdapterSchemaGeneratorTest.java
@@ -72,6 +72,6 @@ public class AdapterSchemaGeneratorTest {
     );
     assertEquals("description", properties.get(0).getDescription());
     assertEquals(PropertyScope.DIMENSION_PROPERTY.name(), properties.get(0).getPropertyScope());
-    assertEquals("semanticType", properties.get(0).getDomainProperties().get(0).toString());
+    assertEquals("semanticType", properties.get(0).getSemanticType());
   }
 }
diff --git a/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java b/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
index 5b7085784e..0c09c71977 100644
--- a/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
+++ b/streampipes-data-explorer-iotdb/src/test/java/org/apache/streampipes/dataexplorer/iotdb/IotDbPropertyConverterTest.java
@@ -18,12 +18,13 @@
 
 package org.apache.streampipes.dataexplorer.iotdb;
 
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.model.runtime.field.PrimitiveField;
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.vocabulary.SO;
 import org.apache.streampipes.vocabulary.XSD;
+
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -42,7 +43,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyInteger() {
 
-    var property = new EventPropertyPrimitive(XSD.INTEGER.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.INTEGER.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 5);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -55,7 +56,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyString() {
 
-    var property = new EventPropertyPrimitive(XSD.STRING.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.STRING.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", "value");
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -68,7 +69,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyFloat() {
 
-    var property = new EventPropertyPrimitive(XSD.FLOAT.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.FLOAT.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 0.5f);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -81,7 +82,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyNumber() {
 
-    var property = new EventPropertyPrimitive(SO.NUMBER, "test", null, null);
+    var property = new EventPropertyPrimitive(SO.NUMBER, "test", null, "");
     var field = new PrimitiveField("test", "test", 5.24);
 
     var result = new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest");
@@ -94,7 +95,7 @@ public class IotDbPropertyConverterTest {
   @Test
   public void convertPrimitivePropertyUnknown() {
 
-    var property = new EventPropertyPrimitive(XSD.ANY_TYPE.toString(), "test", null, null);
+    var property = new EventPropertyPrimitive(XSD.ANY_TYPE.toString(), "test", null, "");
     var field = new PrimitiveField("test", "test", 5);
 
     assertThrows(SpRuntimeException.class, () -> new IotDbPropertyConverter().convertPrimitiveProperty(property, field, "sanitizedTest"));
diff --git a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
index 50026e5757..e84ba4c087 100644
--- a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
+++ b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/ListPropertyMatchTest.java
@@ -24,7 +24,6 @@ import org.apache.streampipes.model.schema.EventPropertyList;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -33,13 +32,12 @@ public class ListPropertyMatchTest {
 
   @Test
   public void matchSameDomainProperty() {
-    List<URI> domainProperties = new ArrayList<>();
-    domainProperties.add(URI.create("http://test.org/property"));
+    var semanticType = "http://test.org/property";
 
     EventPropertyList offer = new EventPropertyList();
-    offer.setDomainProperties(domainProperties);
+    offer.setSemanticType(semanticType);
     EventPropertyList requirement = new EventPropertyList();
-    requirement.setDomainProperties(domainProperties);
+    requirement.setSemanticType(semanticType);
 
     List<MatchingResultMessage> errorLog = new ArrayList<>();
 
@@ -61,4 +59,4 @@ public class ListPropertyMatchTest {
     Assertions.assertTrue(result);
   }
 
-}
\ No newline at end of file
+}
diff --git a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
similarity index 63%
rename from streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java
rename to streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
index 07038bd632..12d004b996 100644
--- a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestDomainPropertyMatch.java
+++ b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/v2/TestSemanticTypeMatch.java
@@ -24,37 +24,32 @@ import org.apache.streampipes.vocabulary.Geo;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
-public class TestDomainPropertyMatch {
+public class TestSemanticTypeMatch {
 
   @Test
-  public void testPositiveDomainPropertyMatch() {
+  public void testPositiveSemanticTypeMatch() {
 
-    List<URI> offeredDomainProperty = buildDomainProperties(Geo.LAT);
-    List<URI> requiredDomainProperty = buildDomainProperties(Geo.LAT);
+    var offeredDomainProperty = Geo.LAT;
+    var requiredDomainProperty = Geo.LAT;
 
     List<MatchingResultMessage> resultMessage = new ArrayList<>();
 
-    boolean matches = new DomainPropertyMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
+    boolean matches = new SemanticTypeMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
     Assertions.assertTrue(matches);
   }
 
   @Test
-  public void testNegativeDomainPropertyMatch() {
+  public void testNegativeSemanticTypeMatch() {
 
-    List<URI> offeredDomainProperty = buildDomainProperties(Geo.LAT);
-    List<URI> requiredDomainProperty = buildDomainProperties(Geo.LNG);
+    var offeredDomainProperty = Geo.LAT;
+    var requiredDomainProperty = Geo.LNG;
 
     List<MatchingResultMessage> resultMessage = new ArrayList<>();
 
-    boolean matches = new DomainPropertyMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
+    boolean matches = new SemanticTypeMatch().match(offeredDomainProperty, requiredDomainProperty, resultMessage);
     Assertions.assertFalse(matches);
   }
-
-  private List<URI> buildDomainProperties(String name) {
-    return List.of(URI.create(name));
-  }
 }
diff --git a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
index fc5c1babc3..61439a9638 100644
--- a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
+++ b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventPropertyPrimitiveTestBuilder.java
@@ -21,7 +21,6 @@ import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.PropertyScope;
 
 import java.net.URI;
-import java.util.List;
 
 public class EventPropertyPrimitiveTestBuilder
     extends EventPropertyTestBuilder<EventPropertyPrimitive, EventPropertyPrimitiveTestBuilder> {
@@ -41,7 +40,7 @@ public class EventPropertyPrimitiveTestBuilder
   }
 
   public EventPropertyPrimitiveTestBuilder withSemanticType(String semanticType) {
-    this.eventProperty.setDomainProperties(List.of(URI.create(semanticType)));
+    this.eventProperty.setSemanticType(semanticType);
     return this;
   }
 
diff --git a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
index 97e420af86..e46e0ee1b8 100644
--- a/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
+++ b/streampipes-test-utils/src/main/java/org/apache/streampipes/test/generator/EventStreamGenerator.java
@@ -23,7 +23,6 @@ import org.apache.streampipes.model.schema.EventSchema;
 import org.apache.streampipes.test.generator.grounding.EventGroundingGenerator;
 import org.apache.streampipes.vocabulary.XSD;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -43,7 +42,7 @@ public class EventStreamGenerator {
         .getEventSchema()
         .setEventProperties(runtimeNames
             .stream()
-            .map(r -> new EventPropertyPrimitive(XSD.INTEGER.toString(), r, "", new ArrayList<>()))
+            .map(r -> new EventPropertyPrimitive(XSD.INTEGER.toString(), r, "", ""))
             .collect(Collectors.toList()));
 
     return stream;