You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by dr...@apache.org on 2016/08/26 09:42:05 UTC
incubator-unomi git commit: UNOMI-32 : Improved profile updates to
only merge specified properties. Send event only if profile is modifed. Also
merge proeprty types on save.
Repository: incubator-unomi
Updated Branches:
refs/heads/master b2cb9ee0d -> ec58db2c9
UNOMI-32 : Improved profile updates to only merge specified properties. Send event only if profile is modifed. Also merge proeprty types on save.
Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/ec58db2c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/ec58db2c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/ec58db2c
Branch: refs/heads/master
Commit: ec58db2c9edc75ea5d5acbf2d0bc902a724748bc
Parents: b2cb9ee
Author: Thomas Draier <dr...@apache.org>
Authored: Fri Aug 26 11:41:54 2016 +0200
Committer: Thomas Draier <dr...@apache.org>
Committed: Fri Aug 26 11:41:54 2016 +0200
----------------------------------------------------------------------
.../java/org/apache/unomi/api/PropertyType.java | 16 ++--
.../unomi/api/services/ProfileService.java | 8 ++
.../unomi/rest/ProfileServiceEndPoint.java | 12 +--
.../services/services/ProfileServiceImpl.java | 77 ++++++++++++++++++--
4 files changed, 94 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/ec58db2c/api/src/main/java/org/apache/unomi/api/PropertyType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/unomi/api/PropertyType.java b/api/src/main/java/org/apache/unomi/api/PropertyType.java
index ab58990..4d5bf6f 100644
--- a/api/src/main/java/org/apache/unomi/api/PropertyType.java
+++ b/api/src/main/java/org/apache/unomi/api/PropertyType.java
@@ -44,12 +44,12 @@ public class PropertyType extends MetadataItem {
private List<NumericRange> numericRanges = new ArrayList<>();
private List<IpRange> ipRanges = new ArrayList<>();
private Set<String> automaticMappingsFrom = new HashSet<>();
- private double rank;
+ private Double rank;
private String mergeStrategy;
private Set<Tag> tags = new TreeSet<Tag>();
private Set<String> tagIds = new LinkedHashSet<String>();
- private boolean multivalued;
- private boolean protekted = false;
+ private Boolean multivalued;
+ private Boolean protekted;
/**
* Instantiates a new Property type.
@@ -210,7 +210,7 @@ public class PropertyType extends MetadataItem {
*
* @return the rank of this PropertyType for ordering purpose
*/
- public double getRank() {
+ public Double getRank() {
return rank;
}
@@ -219,7 +219,7 @@ public class PropertyType extends MetadataItem {
*
* @param rank the rank of this PropertyType for ordering purpose
*/
- public void setRank(double rank) {
+ public void setRank(Double rank) {
this.rank = rank;
}
@@ -300,7 +300,7 @@ public class PropertyType extends MetadataItem {
*
* @return {@code true} if properties of this type should be multi-valued, {@code false} otherwise
*/
- public boolean isMultivalued() {
+ public Boolean isMultivalued() {
return multivalued;
}
@@ -309,7 +309,7 @@ public class PropertyType extends MetadataItem {
*
* @param multivalued {@code true} if properties of this type should be multi-valued, {@code false} otherwise
*/
- public void setMultivalued(boolean multivalued) {
+ public void setMultivalued(Boolean multivalued) {
this.multivalued = multivalued;
}
@@ -320,7 +320,7 @@ public class PropertyType extends MetadataItem {
*
* @return {@code true} if properties of this type are protected, {@code false} otherwise
*/
- public boolean isProtected() {
+ public Boolean isProtected() {
return protekted;
}
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/ec58db2c/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
index c13036a..a998e5e 100644
--- a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java
@@ -106,6 +106,14 @@ public interface ProfileService {
Profile save(Profile profile);
/**
+ * Merge the specified profile properties in an existing profile,or save new profile if it does not exist yet
+ *
+ * @param profile the profile to be saved
+ * @return the newly saved profile
+ */
+ boolean saveOrmerge(Profile profile);
+
+ /**
* Removes the profile (or persona if the {@code persona} parameter is set to {@code true}) identified by the specified identifier.
*
* @param profileId the identifier of the profile or persona to delete
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/ec58db2c/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
index b806378..038178d 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
@@ -193,11 +193,13 @@ public class ProfileServiceEndPoint {
@POST
@Path("/")
public Profile save(Profile profile) {
- // TODO: check that the profile was actually updated correctly before sending the event
- Event profileUpdated = new Event("profileUpdated", null, profile, null, null, profile, new Date());
- profileUpdated.setPersistent(false);
- eventService.send(profileUpdated);
- return profileService.save(profile);
+ if (profileService.saveOrmerge(profile)) {
+ Event profileUpdated = new Event("profileUpdated", null, profile, null, null, profile, new Date());
+ profileUpdated.setPersistent(false);
+ eventService.send(profileUpdated);
+ }
+
+ return profile;
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/ec58db2c/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
index 22e6227..aee8832 100644
--- a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
@@ -17,6 +17,8 @@
package org.apache.unomi.services.services;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.unomi.api.*;
import org.apache.unomi.api.conditions.Condition;
@@ -278,12 +280,13 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
@Override
public boolean setPropertyType(PropertyType property) {
- PropertyType previous = null;
- if ((previous = persistenceService.load(property.getItemId(), PropertyType.class)) != null) {
- previous.getAutomaticMappingsFrom().addAll(property.getAutomaticMappingsFrom());
- property = previous;
+ PropertyType previousProperty = persistenceService.load(property.getItemId(), PropertyType.class);
+ if (previousProperty == null) {
+ return persistenceService.save(property);
+ } else if (merge(previousProperty, property)) {
+ return persistenceService.save(previousProperty);
}
- return persistenceService.save(property);
+ return false;
}
@Override
@@ -362,7 +365,7 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
// TODO may be moved this in a specific Export Utils Class and improve it to handle date format, ...
private void handleExportProperty(StringBuilder sb, Object propertyValue, PropertyType propertyType) {
- if (propertyValue instanceof Collection && propertyType != null && propertyType.isMultivalued()) {
+ if (propertyValue instanceof Collection && propertyType != null && propertyType.isMultivalued() != null && propertyType.isMultivalued() ) {
Collection propertyValues = (Collection) propertyValue;
Collection encodedValues = new ArrayList(propertyValues.size());
for (Object value : propertyValues) {
@@ -397,6 +400,17 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
return persistenceService.load(profile.getItemId(), Profile.class);
}
+ public boolean saveOrmerge(Profile profile) {
+ Profile previousProfile = persistenceService.load(profile.getItemId(), Profile.class);
+ if (previousProfile == null) {
+ return persistenceService.save(profile);
+ } else if (merge(previousProfile, profile)) {
+ return persistenceService.save(previousProfile);
+ }
+
+ return false;
+ }
+
public Persona savePersona(Persona profile) {
if (persistenceService.load(profile.getItemId(), Persona.class) == null) {
Session session = new PersonaSession(UUID.randomUUID().toString(), profile, new Date());
@@ -736,4 +750,55 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
}
}
+ private <T> boolean merge(T target, T object) {
+ if (object != null) {
+ try {
+ Map<String,Object> objectValues = PropertyUtils.describe(object);
+ Map<String,Object> targetValues = PropertyUtils.describe(target);
+ if (merge(targetValues, objectValues)) {
+ BeanUtils.populate(target, targetValues);
+ return true;
+ }
+ } catch (ReflectiveOperationException e) {
+ logger.error("Cannot merge properties",e);
+ }
+ }
+ return false;
+ }
+
+ private boolean merge(Map<String,Object> target, Map<String,Object> object) {
+ boolean changed = false;
+ for (Map.Entry<String, Object> previousEntry : object.entrySet()) {
+ if (previousEntry.getValue() != null) {
+ if (previousEntry.getValue() instanceof Collection) {
+ Collection currentCollection = (Collection) target.get(previousEntry.getKey());
+ if (currentCollection != null) {
+ if (!currentCollection.containsAll((Collection) previousEntry.getValue())) {
+ changed |= currentCollection.addAll((Collection) previousEntry.getValue());
+ }
+ } else {
+ target.put(previousEntry.getKey(), previousEntry.getValue());
+ changed = true;
+ }
+ } else if (previousEntry.getValue() instanceof Map) {
+ Map<String,Object> currentMap = (Map) target.get(previousEntry.getKey());
+ if (currentMap == null) {
+ target.put(previousEntry.getKey(), previousEntry.getValue());
+ changed = true;
+ } else {
+ changed |= merge(currentMap, (Map) previousEntry.getValue());
+ }
+ } else if (previousEntry.getValue().getClass().getPackage().getName().equals("java.lang")) {
+ if (previousEntry.getValue() != null && !previousEntry.getValue().equals(target.get(previousEntry.getKey()))) {
+ target.put(previousEntry.getKey(), previousEntry.getValue());
+ changed = true;
+ }
+ } else {
+ changed |= merge(target.get(previousEntry.getKey()), previousEntry.getValue());
+ }
+ }
+ }
+ return changed;
+ }
+
}