You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by jk...@apache.org on 2021/03/26 14:02:44 UTC
[unomi] branch unomi-1.5.x updated: UNOMI-448 : Create generic
action to copy properties to profile (#268)
This is an automated email from the ASF dual-hosted git repository.
jkevan pushed a commit to branch unomi-1.5.x
in repository https://gitbox.apache.org/repos/asf/unomi.git
The following commit(s) were added to refs/heads/unomi-1.5.x by this push:
new 5e2c2f4 UNOMI-448 : Create generic action to copy properties to profile (#268)
5e2c2f4 is described below
commit 5e2c2f4c07a8066050d18ef3e3c249fd9bf37489
Author: jsinovassin <58...@users.noreply.github.com>
AuthorDate: Fri Mar 26 14:41:31 2021 +0100
UNOMI-448 : Create generic action to copy properties to profile (#268)
* UNOMI-448 : Create generic action to copy properties to profile
* handle feedback
* handle feedback
---
.../test/java/org/apache/unomi/itests/AllITs.java | 1 +
.../test/java/org/apache/unomi/itests/BaseIT.java | 8 +-
.../unomi/itests/CopyPropertiesActionIT.java | 275 +++++++++++++++++++++
itests/src/test/resources/testCopyProperties.json | 26 ++
.../testCopyPropertiesWithoutSystemTags.json | 23 ++
itests/src/test/resources/testLogin.json | 2 +-
.../baseplugin/actions/CopyPropertiesAction.java | 115 +++++++++
.../actions/allEventToProfilePropertiesAction.json | 5 +-
.../META-INF/cxs/actions/copyPropertiesAction.json | 30 +++
.../resources/OSGI-INF/blueprint/blueprint.xml | 10 +
10 files changed, 489 insertions(+), 6 deletions(-)
diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
index 284b04e..b4ecd56 100644
--- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java
+++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
@@ -41,6 +41,7 @@ import org.junit.runners.Suite.SuiteClasses;
ProfileMergeIT.class,
EventServiceIT.class,
PropertiesUpdateActionIT.class,
+ CopyPropertiesActionIT.class,
ModifyConsentIT.class,
PatchIT.class,
ContextServletIT.class,
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index a3d1d27..42e1318 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -59,7 +59,7 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*;
/**
* Base class for integration tests.
- *
+ *
* @author kevan
*/
@RunWith(PaxExam.class)
@@ -67,7 +67,7 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*;
public abstract class BaseIT {
private final static Logger LOGGER = LoggerFactory.getLogger(BaseIT.class);
-
+
protected static final String HTTP_PORT = "8181";
protected static final String URL = "http://localhost:" + HTTP_PORT;
protected static final String KARAF_DIR = "target/exam";
@@ -140,6 +140,10 @@ public abstract class BaseIT {
"src/test/resources/6-actors-test.csv")),
replaceConfigurationFile("data/tmp/testLogin.json", new File(
"src/test/resources/testLogin.json")),
+ replaceConfigurationFile("data/tmp/testCopyProperties.json", new File(
+ "src/test/resources/testCopyProperties.json")),
+ replaceConfigurationFile("data/tmp/testCopyPropertiesWithoutSystemTags.json", new File(
+ "src/test/resources/testCopyPropertiesWithoutSystemTags.json")),
replaceConfigurationFile("data/tmp/testLoginEventCondition.json", new File(
"src/test/resources/testLoginEventCondition.json")),
keepRuntimeFolder(),
diff --git a/itests/src/test/java/org/apache/unomi/itests/CopyPropertiesActionIT.java b/itests/src/test/java/org/apache/unomi/itests/CopyPropertiesActionIT.java
new file mode 100644
index 0000000..3be376d
--- /dev/null
+++ b/itests/src/test/java/org/apache/unomi/itests/CopyPropertiesActionIT.java
@@ -0,0 +1,275 @@
+/*
+ * 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.unomi.itests;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.PropertyType;
+import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.api.services.RulesService;
+import org.apache.unomi.persistence.spi.CustomObjectMapper;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerSuite;
+import org.ops4j.pax.exam.util.Filter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by amidani on 12/10/2017.
+ */
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerSuite.class)
+public class CopyPropertiesActionIT extends BaseIT {
+ private final static Logger LOGGER = LoggerFactory.getLogger(CopyPropertiesActionIT.class);
+
+ private final static String EMPTY_PROFILE = "empty-profile";
+ private final static String PROFILE_WITH_PROPERTIES = "profile-with-properties";
+ private final static String ARRAY_PARAM_NAME = "arrayParam";
+ public static final String SINGLE_PARAM_NAME = "singleParam";
+
+ @Inject
+ @Filter(timeout = 600000)
+ protected RulesService rulesService;
+ @Inject
+ @Filter(timeout = 600000)
+ protected ProfileService profileService;
+ @Inject
+ @Filter(timeout = 600000)
+ protected EventService eventService;
+
+ @Before
+ public void setUp() throws IOException, InterruptedException {
+ Profile profile = new Profile();
+ profile.setItemId(PROFILE_WITH_PROPERTIES);
+ profile.setProperties(new HashMap<>());
+ profile.setProperty("lastName", "Jose"); // property that have a propertyType registered in the system
+ profile.setProperty("singleValue", "A single value");
+ profile.setProperty("existingArray", Arrays.asList("element1", "element2"));
+ profileService.save(profile);
+ LOGGER.info("Profile saved with ID [{}].", profile.getItemId());
+
+ Profile profileTarget = new Profile();
+ profileTarget.setItemId(EMPTY_PROFILE);
+ profileService.save(profileTarget);
+ LOGGER.info("Profile saved with ID [{}].", profileTarget.getItemId());
+
+ refreshPersistence();
+ }
+
+ @After
+ public void cleanUp() throws IOException, InterruptedException {
+ profileService.delete(PROFILE_WITH_PROPERTIES, false);
+ profileService.delete(EMPTY_PROFILE, false);
+ profileService.deletePropertyType(ARRAY_PARAM_NAME);
+ profileService.deletePropertyType(SINGLE_PARAM_NAME);
+ refreshPersistence();
+ }
+
+ private void initializePropertyType() {
+ Metadata metadata = new Metadata();
+ metadata.setSystemTags(new HashSet<>(Arrays.asList("urlParameters")));
+ metadata.setId(ARRAY_PARAM_NAME);
+ metadata.setName("Array parameter");
+
+ PropertyType propertyType1 = new PropertyType();
+ propertyType1.setItemId(ARRAY_PARAM_NAME);
+ propertyType1.setMetadata(metadata);
+ propertyType1.setTarget("profiles");
+ propertyType1.setValueTypeId("string");
+ propertyType1.setMultivalued(true);
+
+ Metadata metadata2 = new Metadata();
+ metadata2.setSystemTags(new HashSet<>(Arrays.asList("urlParameters")));
+ metadata2.setId(SINGLE_PARAM_NAME);
+ metadata2.setName("Single parameters");
+
+ PropertyType propertyType2 = new PropertyType();
+ propertyType2.setItemId(SINGLE_PARAM_NAME);
+ propertyType2.setMetadata(metadata2);
+ propertyType2.setTarget("profiles");
+ propertyType2.setValueTypeId("string");
+ propertyType2.setMultivalued(false);
+
+ profileService.setPropertyType(propertyType1);
+ profileService.setPropertyType(propertyType2);
+ }
+
+ private void initializePropertyTypeWithDifferentSystemTag() {
+ Metadata metadata = new Metadata();
+ metadata.setSystemTags(new HashSet<>(Arrays.asList("shouldBeAbsent")));
+ metadata.setId(ARRAY_PARAM_NAME);
+ metadata.setName("Array parameter");
+
+ PropertyType propertyType1 = new PropertyType();
+ propertyType1.setItemId(ARRAY_PARAM_NAME);
+ propertyType1.setMetadata(metadata);
+ propertyType1.setTarget("profiles");
+ propertyType1.setValueTypeId("string");
+ propertyType1.setMultivalued(true);
+
+ profileService.setPropertyType(propertyType1);
+ }
+
+ private void createRule(String filename) throws IOException, InterruptedException {
+ Rule rule = CustomObjectMapper.getObjectMapper().readValue(new File(filename).toURI().toURL(), Rule.class);
+ rulesService.setRule(rule);
+ Thread.sleep(2000);
+ }
+
+ private Event sendCopyPropertyEvent(Map<String, Object> properties, String profileType) {
+ Profile profile = profileService.load(profileType);
+
+ Event event = new Event("copyProperties", null, profile, null, null, profile, new Date());
+ event.setPersistent(false);
+
+ event.setProperty("urlParameters", properties);
+
+ eventService.send(event);
+ return event;
+ }
+
+ @Test
+ public void testCopyProperties_copyMultipleValueWithoutExistingPropertyTypeAndWithoutExistingValue()
+ throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyPropertiesWithoutSystemTags.json");
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(ARRAY_PARAM_NAME, Arrays.asList("valueA", "valueB"));
+
+ Event event = sendCopyPropertyEvent(properties, EMPTY_PROFILE);
+
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty(ARRAY_PARAM_NAME)).contains("valueA"));
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty(ARRAY_PARAM_NAME)).contains("valueB"));
+ }
+
+ @Test
+ public void testCopyProperties_tryCopyArrayOnExistingSingleValue() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyPropertiesWithoutSystemTags.json");
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("singleValue", Arrays.asList("valueA", "valueB"));
+
+ Event event = sendCopyPropertyEvent(properties, PROFILE_WITH_PROPERTIES);
+
+ Assert.assertTrue(((String) event.getProfile().getProperty("singleValue")).equals("A single value"));
+ }
+
+ @Test
+ public void testCopyProperties_replaceSingleValue() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyPropertiesWithoutSystemTags.json");
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("singleValue", "New value");
+
+ Event event = sendCopyPropertyEvent(properties, PROFILE_WITH_PROPERTIES);
+
+ Assert.assertTrue(((String) event.getProfile().getProperty("singleValue")).equals("New value"));
+ }
+
+ @Test
+ public void testCopyProperties_copyArrayIntoExistingArray() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyPropertiesWithoutSystemTags.json");
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("existingArray", Arrays.asList("valueA", "valueB"));
+
+ Event event = sendCopyPropertyEvent(properties, PROFILE_WITH_PROPERTIES);
+
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty("existingArray")).contains("element1"));
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty("existingArray")).contains("element2"));
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty("existingArray")).contains("valueA"));
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty("existingArray")).contains("valueB"));
+ }
+
+ @Test
+ public void testCopyProperties_copyArrayWithPropertyType() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyPropertiesWithoutSystemTags.json");
+
+ initializePropertyType();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(ARRAY_PARAM_NAME, Arrays.asList("valueA", "valueB"));
+
+ Event event = sendCopyPropertyEvent(properties, EMPTY_PROFILE);
+
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty(ARRAY_PARAM_NAME)).contains("valueA"));
+ Assert.assertTrue(((List<String>) event.getProfile().getProperty(ARRAY_PARAM_NAME)).contains("valueB"));
+ }
+
+ @Test
+ public void testCopyProperties_tryCopyArrayWithPropertyTypeIntoSingleValue() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyProperties.json");
+
+ initializePropertyType();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(SINGLE_PARAM_NAME, Arrays.asList("valueA", "valueB"));
+
+ Event event = sendCopyPropertyEvent(properties, EMPTY_PROFILE);
+
+ Assert.assertNull(event.getProfile().getProperty(SINGLE_PARAM_NAME));
+ }
+
+ @Test
+ public void testCopyProperties_replaceSingleValueWithPropertyType() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyProperties.json");
+
+ initializePropertyType();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(SINGLE_PARAM_NAME, "New value");
+
+ Event event = sendCopyPropertyEvent(properties, EMPTY_PROFILE);
+
+ Assert.assertTrue(((String) event.getProfile().getProperty(SINGLE_PARAM_NAME)).equals("New value"));
+ }
+
+ @Test
+ public void testCopyProperties_mandatorySystemTagsNotPresent() throws IOException, InterruptedException {
+ createRule("data/tmp/testCopyProperties.json");
+
+ initializePropertyTypeWithDifferentSystemTag();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(ARRAY_PARAM_NAME, Arrays.asList("New value"));
+
+ Event event = sendCopyPropertyEvent(properties, EMPTY_PROFILE);
+
+ Assert.assertTrue(event.getProfile().getProperty(ARRAY_PARAM_NAME) == null);
+ }
+}
diff --git a/itests/src/test/resources/testCopyProperties.json b/itests/src/test/resources/testCopyProperties.json
new file mode 100644
index 0000000..44354e9
--- /dev/null
+++ b/itests/src/test/resources/testCopyProperties.json
@@ -0,0 +1,26 @@
+{
+ "metadata": {
+ "id": "copyProperties",
+ "name": "Copy properties to profile",
+ "description": "Copy properties to profile",
+ "readOnly": true
+ },
+ "condition": {
+ "type": "eventTypeCondition",
+ "parameterValues": {
+ "eventTypeId": "copyProperties"
+ }
+ },
+ "actions": [
+ {
+ "type": "copyPropertiesAction",
+ "parameterValues": {
+ "rootProperty": "properties.urlParameters",
+ "mandatoryPropTypeSystemTag": [
+ "urlParameters"
+ ],
+ "singleValueStrategy": "alwaysSet"
+ }
+ }
+ ]
+}
diff --git a/itests/src/test/resources/testCopyPropertiesWithoutSystemTags.json b/itests/src/test/resources/testCopyPropertiesWithoutSystemTags.json
new file mode 100644
index 0000000..548dd20
--- /dev/null
+++ b/itests/src/test/resources/testCopyPropertiesWithoutSystemTags.json
@@ -0,0 +1,23 @@
+{
+ "metadata": {
+ "id": "copyProperties",
+ "name": "Copy properties to profile",
+ "description": "Copy properties to profile",
+ "readOnly": true
+ },
+ "condition": {
+ "type": "eventTypeCondition",
+ "parameterValues": {
+ "eventTypeId": "copyProperties"
+ }
+ },
+ "actions": [
+ {
+ "type": "copyPropertiesAction",
+ "parameterValues": {
+ "rootProperty": "properties.urlParameters",
+ "singleValueStrategy": "alwaysSet"
+ }
+ }
+ ]
+}
diff --git a/itests/src/test/resources/testLogin.json b/itests/src/test/resources/testLogin.json
index e5a3511..fce5a3d 100644
--- a/itests/src/test/resources/testLogin.json
+++ b/itests/src/test/resources/testLogin.json
@@ -31,4 +31,4 @@
"type": "allEventToProfilePropertiesAction"
}
]
-}
\ No newline at end of file
+}
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java
new file mode 100644
index 0000000..7d0b9cf
--- /dev/null
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java
@@ -0,0 +1,115 @@
+/*
+ * 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.unomi.plugins.baseplugin.actions;
+
+import org.apache.commons.beanutils.BeanUtilsBean;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.PropertyType;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.actions.ActionExecutor;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.persistence.spi.PropertyHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CopyPropertiesAction implements ActionExecutor {
+
+ private static final Logger logger = LoggerFactory.getLogger(CopyPropertiesAction.class);
+ private ProfileService profileService;
+
+ public void setProfileService(ProfileService profileService) {
+ this.profileService = profileService;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public int execute(Action action, Event event) {
+ boolean atLeastOnechanged = false;
+ List<String> mandatoryPropTypeSystemTags = (List<String>) action.getParameterValues().get("mandatoryPropTypeSystemTag");
+ String singleValueStrategy = (String) action.getParameterValues().get("singleValueStrategy");
+ for (Map.Entry<String, Object> entry : getEventPropsToCopy(action, event).entrySet()) {
+ // propType Check
+ PropertyType propertyType = profileService.getPropertyType(entry.getKey());
+ Object previousValue = event.getProfile().getProperty(entry.getKey());
+ if (mandatoryPropTypeSystemTags != null && mandatoryPropTypeSystemTags.size() > 0) {
+ if (propertyType == null || propertyType.getMetadata() == null || propertyType.getMetadata().getSystemTags() == null
+ || !propertyType.getMetadata().getSystemTags().containsAll(mandatoryPropTypeSystemTags)) {
+ continue;
+ }
+ }
+ String propertyName = "properties." + entry.getKey();
+ boolean changed = false;
+ if (previousValue == null && propertyType == null) {
+ changed = PropertyHelper.setProperty(event.getProfile(), propertyName, entry.getValue(), "alwaysSet");
+ } else {
+ boolean propertyTypeIsMultiValued =
+ propertyType != null && propertyType.isMultivalued() != null && propertyType.isMultivalued();
+ boolean multipleIsExpected = previousValue != null ? previousValue instanceof List : propertyTypeIsMultiValued;
+
+ if (multipleIsExpected) {
+ changed = PropertyHelper.setProperty(event.getProfile(), propertyName, entry.getValue(), "addValues");
+ } else if (entry.getValue() instanceof List) {
+ logger.error(
+ "Impossible to copy the property of type List to the profile, either a single value already exist on the profile or the property type is declared as a single value property. Enable debug log level for more information");
+ if (logger.isDebugEnabled()) {
+ logger.debug("cannot copy property {}, because it's a List", entry.getKey());
+ }
+ } else {
+ changed = PropertyHelper.setProperty(event.getProfile(), propertyName, entry.getValue(), singleValueStrategy);
+ }
+ }
+ atLeastOnechanged = atLeastOnechanged || changed;
+ }
+ return atLeastOnechanged ? EventService.PROFILE_UPDATED : EventService.NO_CHANGE;
+ }
+
+ private Map<String, Object> getEventPropsToCopy(Action action, Event event) {
+ Map<String, Object> propsToCopy = new HashMap<String, Object>();
+
+ String rootProperty = (String) action.getParameterValues().get("rootProperty");
+ boolean copyEventProps = false;
+
+ if (StringUtils.isEmpty(rootProperty)) {
+ copyEventProps = true;
+ rootProperty = "target.properties";
+ }
+
+ // copy props from the event.properties
+ if (copyEventProps && event.getProperties() != null) {
+ propsToCopy.putAll(event.getProperties());
+ }
+
+ // copy props from the specified level (default is: target.properties)
+ try {
+ Object targetProperties = BeanUtilsBean.getInstance().getPropertyUtils().getProperty(event, rootProperty);
+ if (targetProperties instanceof Map) {
+ propsToCopy.putAll((Map) targetProperties);
+ }
+ } catch (Exception e) {
+ logger.error("Unable to extract properties to be copied from the event to the profile using root property: {}", rootProperty,
+ e);
+ }
+
+ return propsToCopy;
+ }
+}
diff --git a/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/allEventToProfilePropertiesAction.json b/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/allEventToProfilePropertiesAction.json
index 35d4ade..abf1d29 100644
--- a/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/allEventToProfilePropertiesAction.json
+++ b/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/allEventToProfilePropertiesAction.json
@@ -10,6 +10,5 @@
"readOnly": true
},
"actionExecutor": "allEventToProfileProperties",
- "parameters": [
- ]
-}
\ No newline at end of file
+ "parameters": []
+}
diff --git a/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/copyPropertiesAction.json b/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/copyPropertiesAction.json
new file mode 100644
index 0000000..7c1a834
--- /dev/null
+++ b/plugins/baseplugin/src/main/resources/META-INF/cxs/actions/copyPropertiesAction.json
@@ -0,0 +1,30 @@
+{
+ "metadata": {
+ "id": "copyPropertiesAction",
+ "name": "copyPropertiesAction",
+ "description": "",
+ "systemTags": [
+ "profileTags",
+ "event"
+ ],
+ "readOnly": true
+ },
+ "actionExecutor": "copyProperties",
+ "parameters": [
+ {
+ "id": "setPropertyStrategy",
+ "type": "string",
+ "multivalued": false
+ },
+ {
+ "id": "rootProperty",
+ "type": "string",
+ "multivalued": false
+ },
+ {
+ "id": "mandatoryPropTypeSystemTag",
+ "type": "string",
+ "multivalued": true
+ }
+ ]
+}
diff --git a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 9f7169a..22f01d7 100644
--- a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -171,6 +171,7 @@
</bean>
</service>
+
<!-- Action executors -->
<service interface="org.apache.unomi.api.actions.ActionExecutor">
@@ -184,6 +185,15 @@
<service interface="org.apache.unomi.api.actions.ActionExecutor">
<service-properties>
+ <entry key="actionExecutorId" value="copyProperties"/>
+ </service-properties>
+ <bean class="org.apache.unomi.plugins.baseplugin.actions.CopyPropertiesAction">
+ <property name="profileService" ref="profileService"/>
+ </bean>
+ </service>
+
+ <service interface="org.apache.unomi.api.actions.ActionExecutor">
+ <service-properties>
<entry key="actionExecutorId" value="eventToProfileProperty"/>
</service-properties>
<bean class="org.apache.unomi.plugins.baseplugin.actions.EventToProfilePropertyAction"/>