This is an automated email from the ASF dual-hosted git repository. shuber pushed a commit to branch unomi-1.5.x in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 94f7f0862388584ace5a5d3c2bcfb2e7245462d1 Author: giladw <[email protected]> AuthorDate: Wed Apr 21 18:18:17 2021 +0300 when merging profiles properties flatten nested properties (#262) (cherry picked from commit cbe3849f5e23335d4acbac294d019a1bdc5b491d) --- .../unomi/persistence/spi/PropertyHelper.java | 28 ++++++++++++++++++++++ .../services/impl/profiles/ProfileServiceImpl.java | 17 ++++++------- .../DefaultPropertyMergeStrategyExecutor.java | 7 +++--- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java index 38a09e0..6315025 100644 --- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java @@ -21,11 +21,13 @@ import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.NestedNullException; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.beanutils.expression.DefaultResolver; +import org.apache.unomi.api.Profile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.stream.Collectors; /** * Helper method for properties @@ -194,5 +196,31 @@ public class PropertyHelper { } } + public static Map<String, Object> flatten(Map<String, Object> in) { + return in.entrySet().stream() + .filter(entry -> entry.getValue() != null) + .flatMap(entry -> flatten(entry).entrySet().stream()) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue)); + } + + private static Map<String, Object> flatten(Map.Entry<String, Object> in) { + // for other then Map objects return them + if (!Map.class.isInstance(in.getValue())) { + return Collections.singletonMap(in.getKey(), in.getValue()); + } + // extract the key prefix for nested objects + String prefix = in.getKey(); + Map<String, Object> values = (Map<String, Object>) in.getValue(); + // create a new Map, with prefix added to each key + Map<String, Object> flattenMap = new HashMap<>(); + values.keySet().forEach(key -> { + // use a dot as a joining char + flattenMap.put(prefix + "." + key, values.get(key)); + }); + // use recursion to flatten the structure deeper + return flatten(flattenMap); + } } diff --git a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java index c0cc002..eb63346 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java @@ -599,7 +599,8 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList Set<String> allProfileProperties = new LinkedHashSet<>(); for (Profile profile : profilesToMerge) { - allProfileProperties.addAll(profile.getProperties().keySet()); + final Set<String> flatNestedPropertiesKeys = PropertyHelper.flatten(profile.getProperties()).keySet(); + allProfileProperties.addAll(flatNestedPropertiesKeys); } Collection<PropertyType> profilePropertyTypes = getTargetPropertyTypes("profiles"); @@ -668,12 +669,12 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList // we now have to merge the profile's consents for (Profile profile : profilesToMerge) { if (profile.getConsents() != null && profile.getConsents().size() > 0) { - for(String consentId : profile.getConsents().keySet()) { - if(masterProfile.getConsents().containsKey(consentId)) { - if(masterProfile.getConsents().get(consentId).getRevokeDate().before(new Date())) { + for (String consentId : profile.getConsents().keySet()) { + if (masterProfile.getConsents().containsKey(consentId)) { + if (masterProfile.getConsents().get(consentId).getRevokeDate().before(new Date())) { masterProfile.getConsents().remove(consentId); masterProfileChanged = true; - } else if(masterProfile.getConsents().get(consentId).getStatusDate().before(profile.getConsents().get(consentId).getStatusDate())) { + } else if (masterProfile.getConsents().get(consentId).getStatusDate().before(profile.getConsents().get(consentId).getStatusDate())) { masterProfile.getConsents().replace(consentId, profile.getConsents().get(consentId)); masterProfileChanged = true; } @@ -757,7 +758,7 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList profileCondition.setParameter("comparisonOperator", "equals"); profileCondition.setParameter("propertyValue", profileId); - persistenceService.removeByQuery(profileCondition,Session.class); + persistenceService.removeByQuery(profileCondition, Session.class); } @Override @@ -1038,8 +1039,8 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList changed = true; } } else if (newEntry.getValue().getClass().isEnum()) { - target.put(newEntry.getKey(), newEntry.getValue()); - changed = true; + target.put(newEntry.getKey(), newEntry.getValue()); + changed = true; } else { if (target.get(newEntry.getKey()) != null) { changed |= merge(target.get(newEntry.getKey()), newEntry.getValue()); diff --git a/services/src/main/java/org/apache/unomi/services/mergers/DefaultPropertyMergeStrategyExecutor.java b/services/src/main/java/org/apache/unomi/services/mergers/DefaultPropertyMergeStrategyExecutor.java index e77f7e3..257875c 100644 --- a/services/src/main/java/org/apache/unomi/services/mergers/DefaultPropertyMergeStrategyExecutor.java +++ b/services/src/main/java/org/apache/unomi/services/mergers/DefaultPropertyMergeStrategyExecutor.java @@ -20,6 +20,7 @@ package org.apache.unomi.services.mergers; import org.apache.unomi.api.Profile; import org.apache.unomi.api.PropertyMergeStrategyExecutor; import org.apache.unomi.api.PropertyType; +import org.apache.unomi.persistence.spi.PropertyHelper; import java.util.List; @@ -27,9 +28,9 @@ public class DefaultPropertyMergeStrategyExecutor implements PropertyMergeStrate public boolean mergeProperty(String propertyName, PropertyType propertyType, List<Profile> profilesToMerge, Profile targetProfile) { boolean modified = false; for (Profile profileToMerge : profilesToMerge) { - if (profileToMerge.getProperty(propertyName) != null && - profileToMerge.getProperty(propertyName).toString().length() > 0) { - targetProfile.setProperty(propertyName, profileToMerge.getProperty(propertyName)); + if (profileToMerge.getNestedProperty(propertyName) != null && + profileToMerge.getNestedProperty(propertyName).toString().length() > 0) { + PropertyHelper.setProperty(targetProfile, "properties." + propertyName, profileToMerge.getNestedProperty(propertyName), "alwaysSet"); modified = true; } }
