You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by as...@apache.org on 2021/07/21 14:55:08 UTC
[unomi] 01/01: UNOMI-445 Implement support for multiple profile IDs
on Unomi profiles
This is an automated email from the ASF dual-hosted git repository.
asi pushed a commit to branch UNOMI-445
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 20dd675b293e906c8c8d7d533d4ae47103c94c78
Author: Anatol Sialitski <as...@enonic.com>
AuthorDate: Wed Jun 2 17:10:10 2021 +0300
UNOMI-445 Implement support for multiple profile IDs on Unomi profiles
---
.../java/org/apache/unomi/api/ContextRequest.java | 10 ++++
api/src/main/java/org/apache/unomi/api/Event.java | 5 ++
.../java/org/apache/unomi/api/ProfileAlias.java | 68 ++++++++++++++++++++++
.../apache/unomi/api/services/ProfileService.java | 2 +
.../fetchers/profile/ProfileDataFetcher.java | 3 +
.../org/apache/unomi/itests/ProfileMergeIT.java | 61 +++++++++++++++++++
.../org/apache/unomi/itests/ProfileServiceIT.java | 55 ++++++++++++++---
.../unomi/persistence/spi/CustomObjectMapper.java | 1 +
.../actions/MergeProfilesOnPropertyAction.java | 40 ++++++-------
.../unomi/rest/endpoints/ContextJsonEndpoint.java | 17 +++++-
.../services/impl/profiles/ProfileServiceImpl.java | 28 +++++++++
11 files changed, 256 insertions(+), 34 deletions(-)
diff --git a/api/src/main/java/org/apache/unomi/api/ContextRequest.java b/api/src/main/java/org/apache/unomi/api/ContextRequest.java
index 7a67c06..78c4720 100644
--- a/api/src/main/java/org/apache/unomi/api/ContextRequest.java
+++ b/api/src/main/java/org/apache/unomi/api/ContextRequest.java
@@ -73,6 +73,8 @@ public class ContextRequest {
@Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN)
private String profileId;
+ private String clientId;
+
/**
* Retrieves the source of the context request.
*
@@ -271,4 +273,12 @@ public class ContextRequest {
public void setProfileId(String profileId) {
this.profileId = profileId;
}
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
}
diff --git a/api/src/main/java/org/apache/unomi/api/Event.java b/api/src/main/java/org/apache/unomi/api/Event.java
index ab7e1b0..92e8378 100644
--- a/api/src/main/java/org/apache/unomi/api/Event.java
+++ b/api/src/main/java/org/apache/unomi/api/Event.java
@@ -46,6 +46,11 @@ public class Event extends Item implements TimestampedItem {
* A constant for the name of the attribute that can be used to retrieve the current HTTP response.
*/
public static final String HTTP_RESPONSE_ATTRIBUTE = "http_response";
+ /**
+ * A constant for the name of the attribute that can be used to retrieve the current clientID.
+ */
+ public static final String CLIENT_ID_ATTRIBUTE = "client_id";
+
private static final long serialVersionUID = -1096874942838593575L;
private String eventType;
private String sessionId = null;
diff --git a/api/src/main/java/org/apache/unomi/api/ProfileAlias.java b/api/src/main/java/org/apache/unomi/api/ProfileAlias.java
new file mode 100644
index 0000000..1434b02
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/ProfileAlias.java
@@ -0,0 +1,68 @@
+/*
+ * 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.api;
+
+import java.util.Date;
+
+public class ProfileAlias extends Item {
+
+ public static final String ITEM_TYPE = "profileAlias";
+
+ private String profileID;
+
+ private String clientID;
+
+ private Date creationTime;
+
+ private Date modifiedTime;
+
+ public ProfileAlias() {
+ }
+
+ public String getProfileID() {
+ return profileID;
+ }
+
+ public void setProfileID(String profileID) {
+ this.profileID = profileID;
+ }
+
+ public String getClientID() {
+ return clientID;
+ }
+
+ public void setClientID(String clientID) {
+ this.clientID = clientID;
+ }
+
+ public Date getCreationTime() {
+ return creationTime;
+ }
+
+ public void setCreationTime(Date creationTime) {
+ this.creationTime = creationTime;
+ }
+
+ public Date getModifiedTime() {
+ return modifiedTime;
+ }
+
+ public void setModifiedTime(Date modifiedTime) {
+ this.modifiedTime = modifiedTime;
+ }
+}
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 3b94ed9..b2698c4 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
@@ -108,6 +108,8 @@ public interface ProfileService {
*/
Profile save(Profile profile);
+ void addAliasToProfile(String profileID, String alias, String clientID);
+
/**
* Merge the specified profile properties in an existing profile,or save new profile if it does not exist yet
*
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileDataFetcher.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileDataFetcher.java
index 0a566af..0000065 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileDataFetcher.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/profile/ProfileDataFetcher.java
@@ -52,6 +52,9 @@ public class ProfileDataFetcher extends BaseDataFetcher<CDPProfile> {
profile.setItemType("profile");
profile = profileService.save(profile);
+
+ profileService.addAliasToProfile(profile.getItemId(), profile.getItemId(), profileIDInput.getClient().getId());
+
return new CDPProfile(profile);
}
diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileMergeIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileMergeIT.java
index aa19ae4..c7602d6 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileMergeIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileMergeIT.java
@@ -19,12 +19,15 @@ 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.ProfileAlias;
import org.apache.unomi.api.actions.Action;
import org.apache.unomi.api.conditions.Condition;
import org.apache.unomi.api.rules.Rule;
import org.apache.unomi.api.services.DefinitionsService;
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.PersistenceService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
@@ -38,6 +41,7 @@ import javax.inject.Inject;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.List;
/**
* Integration test for MergeProfilesOnPropertyAction
@@ -52,6 +56,10 @@ public class ProfileMergeIT extends BaseIT {
protected RulesService rulesService;
@Inject @Filter(timeout = 600000)
protected DefinitionsService definitionsService;
+ @Inject @Filter(timeout = 600000)
+ protected ProfileService profileService;
+ @Inject @Filter(timeout = 600000)
+ protected PersistenceService persistenceService;
private final static String TEST_EVENT_TYPE = "mergeProfileTestEventType";
private final static String TEST_RULE_ID = "mergeOnPropertyTest";
@@ -81,6 +89,59 @@ public class ProfileMergeIT extends BaseIT {
Assert.assertEquals(sendEvent().getProfile().getItemId(), TEST_PROFILE_ID);
}
+ @Test
+ public void test() throws InterruptedException {
+ // create rule
+ Condition condition = new Condition(definitionsService.getConditionType("eventTypeCondition"));
+ condition.setParameter("eventTypeId", TEST_EVENT_TYPE);
+
+ final Action action = new Action( definitionsService.getActionType( "mergeProfilesOnPropertyAction"));
+ action.setParameter("mergeProfilePropertyValue", "eventProperty::target.properties(email)");
+ action.setParameter("mergeProfilePropertyName", "mergeIdentifier");
+ action.setParameter("forceEventProfileAsMaster", false);
+
+ Rule rule = new Rule();
+ rule.setMetadata(new Metadata(null, TEST_RULE_ID, TEST_RULE_ID, "Description"));
+ rule.setCondition(condition);
+ rule.setActions(Collections.singletonList(action));
+
+ rulesService.setRule(rule);
+ refreshPersistence();
+
+ // create master profile
+ Profile masterProfile = new Profile();
+ masterProfile.setItemId("masterProfileID");
+ masterProfile.setProperty("email", "username@domain.com");
+ masterProfile.setSystemProperty("mergeIdentifier", "username@domain.com");
+ profileService.save(masterProfile);
+
+ // create event profile
+ Profile eventProfile = new Profile();
+ eventProfile.setItemId("eventProfileID");
+ eventProfile.setProperty("email", "username@domain.com");
+ profileService.save(eventProfile);
+
+ refreshPersistence();
+
+ Event event = new Event(TEST_EVENT_TYPE, null, eventProfile, null, null, eventProfile, new Date());
+ eventService.send(event);
+
+ refreshPersistence();
+
+ Assert.assertNotNull(event.getProfile());
+
+ List<ProfileAlias> profileAliases = persistenceService.getAllItems(ProfileAlias.class);
+
+ Assert.assertFalse(profileAliases.isEmpty());
+
+ List<ProfileAlias> aliases = persistenceService.query("profileID", masterProfile.getItemId(), null, ProfileAlias.class);
+
+ Assert.assertFalse(aliases.isEmpty());
+ Assert.assertEquals(masterProfile.getItemId(), aliases.get(0).getProfileID());
+ Assert.assertEquals(eventProfile.getItemId(), aliases.get(0).getItemId());
+ Assert.assertEquals("defaultClientID", aliases.get(0).getClientID());
+ }
+
private Event sendEvent() {
Profile profile = new Profile();
profile.setProperties(new HashMap<>());
diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
index 25788bd..437097c 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java
@@ -16,20 +16,16 @@
*/
package org.apache.unomi.itests;
+import org.apache.unomi.api.PartialList;
import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.ProfileAlias;
import org.apache.unomi.api.query.Query;
+import org.apache.unomi.api.services.DefinitionsService;
import org.apache.unomi.api.services.ProfileService;
import org.apache.unomi.persistence.spi.PersistenceService;
-import org.apache.unomi.api.services.DefinitionsService;
-import org.apache.unomi.api.PartialList;
-import org.apache.unomi.persistence.elasticsearch.*;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.Before;
-
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerSuite;
@@ -37,10 +33,14 @@ import org.ops4j.pax.exam.util.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;
+import java.util.stream.IntStream;
-import javax.inject.Inject;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
/**
* An integration test for the profile service
@@ -152,5 +152,42 @@ public class ProfileServiceIT extends BaseIT {
assertEquals(testValue, value);
}
+ @Test
+ public void testLoadProfileByAlias() throws Exception {
+ String profileID = "profileID_testLoadProfileByAlias";
+ try {
+ Profile profile = new Profile();
+ profile.setItemId(profileID);
+ profileService.save(profile);
+
+ refreshPersistence();
+
+ IntStream.range(1, 3).forEach(index -> {
+ final String profileAlias = profileID + "_alias_" + index;
+ profileService.addAliasToProfile(profileID, profileAlias, "clientID");
+ });
+
+ refreshPersistence();
+
+ Profile storedProfile = profileService.load(profileID);
+ assertNotNull(storedProfile);
+ assertEquals(profileID, storedProfile.getItemId());
+
+ storedProfile = profileService.load(profileID + "_alias_1");
+ assertNotNull(storedProfile);
+ assertEquals(profileID, storedProfile.getItemId());
+
+ storedProfile = profileService.load(profileID + "_alias_2");
+ assertNotNull(storedProfile);
+ assertEquals(profileID, storedProfile.getItemId());
+ } finally {
+ profileService.delete(profileID, false);
+
+ IntStream.range(1, 3).forEach(index -> {
+ final String profileAlias = profileID + "_alias_" + index;
+ persistenceService.remove(profileAlias, ProfileAlias.class);
+ });
+ }
+ }
}
diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
index 786bbdc..21dbcbd 100644
--- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
+++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java
@@ -79,6 +79,7 @@ public class CustomObjectMapper extends ObjectMapper {
classes.put(ActionType.ITEM_TYPE, ActionType.class);
classes.put(Topic.ITEM_TYPE, Topic.class);
classes.put(SourceItem.ITEM_TYPE, SourceItem.class);
+ classes.put(ProfileAlias.ITEM_TYPE, ProfileAlias.class);
for (Map.Entry<String, Class<? extends Item>> entry : classes.entrySet()) {
propertyTypedObjectDeserializer.registerMapping("itemType=" + entry.getKey(), entry.getValue());
itemDeserializer.registerMapping(entry.getKey(), entry.getValue());
diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
index 24294ff..f1fde71 100644
--- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
+++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java
@@ -32,9 +32,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
public class MergeProfilesOnPropertyAction implements ActionExecutor {
private static final Logger logger = LoggerFactory.getLogger(MergeProfilesOnPropertyAction.class.getName());
@@ -98,10 +100,10 @@ public class MergeProfilesOnPropertyAction implements ActionExecutor {
// Take existing profile
profile = profiles.get(0);
} else {
- // Create a new profile
- if (forceEventProfileAsMaster)
+ if (forceEventProfileAsMaster) {
profile = event.getProfile();
- else {
+ } else {
+ // Create a new profile
profile = new Profile(UUID.randomUUID().toString());
profile.setProperty("firstVisit", event.getTimeStamp());
}
@@ -163,7 +165,7 @@ public class MergeProfilesOnPropertyAction implements ActionExecutor {
final Boolean anonymousBrowsing = privacyService.isRequireAnonymousBrowsing(masterProfileId);
- if (currentSession != null){
+ if (currentSession != null) {
currentSession.setProfile(masterProfile);
if (privacyService.isRequireAnonymousBrowsing(profile)) {
privacyService.setRequireAnonymousBrowsing(masterProfileId, true, event.getSourceId());
@@ -185,13 +187,14 @@ public class MergeProfilesOnPropertyAction implements ActionExecutor {
if (!StringUtils.equals(profileId, masterProfileId)) {
if (currentEvent.isPersistent()) {
persistenceService.update(currentEvent, currentEvent.getTimeStamp(), Event.class, "profileId", anonymousBrowsing ? null : masterProfileId);
- } }
+ }
+ }
for (Profile profile : profiles) {
String profileId = profile.getItemId();
if (!StringUtils.equals(profileId, masterProfileId)) {
List<Session> sessions = persistenceService.query("profileId", profileId, null, Session.class);
- if (currentSession != null){
+ if (currentSession != null) {
if (masterProfileId.equals(profileId) && !sessions.contains(currentSession)) {
sessions.add(currentSession);
}
@@ -207,21 +210,14 @@ public class MergeProfilesOnPropertyAction implements ActionExecutor {
persistenceService.update(event, event.getTimeStamp(), Event.class, "profileId", anonymousBrowsing ? null : masterProfileId);
}
}
- // we must mark all the profiles that we merged into the master as merged with the master, and they will
- // be deleted upon next load
- profile.setMergedWith(masterProfileId);
- Map<String,Object> sourceMap = new HashMap<>();
- sourceMap.put("mergedWith", masterProfileId);
- profile.setSystemProperty("lastUpdated", new Date());
- sourceMap.put("systemProperties", profile.getSystemProperties());
- boolean isExist = persistenceService.load(profile.getItemId(), Profile.class) != null;
-
- if (isExist == false) //save the original event profile is it has been changed
- persistenceService.save(profile);
- else
- persistenceService.update(profile, null, Profile.class, sourceMap,true);
+ String clientId = Objects.requireNonNullElse((String) event.getAttributes().get(Event.CLIENT_ID_ATTRIBUTE), "defaultClientID");
+ profileService.addAliasToProfile(masterProfileId, profile.getItemId(), clientId);
+ boolean isExist = profileService.load(profile.getItemId()) != null;
+ if (isExist) {
+ profileService.delete(profileId, false);
+ }
}
}
} catch (Exception e) {
@@ -246,7 +242,7 @@ public class MergeProfilesOnPropertyAction implements ActionExecutor {
profileIdCookieName + "=" + profile.getItemId() +
"; Path=/" +
"; Max-Age=" + cookieAgeInSeconds +
- (StringUtils.isNotBlank(profileIdCookieDomain) ? ("; Domain=" + profileIdCookieDomain) : "") +
+ (StringUtils.isNotBlank(profileIdCookieDomain) ? ("; Domain=" + profileIdCookieDomain) : "") +
"; SameSite=Lax");
}
}
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
index e2df705..3224484 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
@@ -64,6 +64,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.Objects;
@WebService
@Consumes(MediaType.APPLICATION_JSON)
@@ -73,6 +74,8 @@ import java.util.UUID;
public class ContextJsonEndpoint {
private static final Logger logger = LoggerFactory.getLogger(ContextJsonEndpoint.class.getName());
+ private static final String DEFAULT_CLIENT_ID = "defaultClientId";
+
private boolean sanitizeConditions = Boolean
.parseBoolean(System.getProperty("org.apache.unomi.security.personalization.sanitizeConditions", "true"));
@@ -204,10 +207,11 @@ public class ContextJsonEndpoint {
}
int changes = EventService.NO_CHANGE;
- if (profile == null) {
- // Not a persona, resolve profile now
- boolean profileCreated = false;
+ // Not a persona, resolve profile now
+ boolean profileCreated = false;
+
+ if (profile == null) {
if (profileId == null || invalidateProfile) {
// no profileId cookie was found or the profile has to be invalidated, we generate a new one and create the profile in the profile service
profile = createNewProfile(null, timestamp);
@@ -295,6 +299,7 @@ public class ContextJsonEndpoint {
profileUpdated.setPersistent(false);
profileUpdated.getAttributes().put(Event.HTTP_REQUEST_ATTRIBUTE, request);
profileUpdated.getAttributes().put(Event.HTTP_RESPONSE_ATTRIBUTE, response);
+ profileUpdated.getAttributes().put(Event.CLIENT_ID_ATTRIBUTE, DEFAULT_CLIENT_ID);
if (logger.isDebugEnabled()) {
logger.debug("Received event {} for profile={} {} target={} timestamp={}", profileUpdated.getEventType(),
@@ -322,6 +327,12 @@ public class ContextJsonEndpoint {
if ((changes & EventService.PROFILE_UPDATED) == EventService.PROFILE_UPDATED) {
profileService.save(profile);
contextResponse.setProfileId(profile.getItemId());
+
+ if (profileCreated) {
+ String clientId = Objects.requireNonNullElse(contextRequest.getClientId(), DEFAULT_CLIENT_ID);
+ String profileMasterId = Objects.requireNonNullElse(profile.getMergedWith(), profile.getItemId());
+ profileService.addAliasToProfile(profileMasterId, profile.getItemId(), clientId );
+ }
}
if ((changes & EventService.SESSION_UPDATED) == EventService.SESSION_UPDATED && session != null) {
profileService.saveSession(session);
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 38356cf..6f984c6 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
@@ -27,6 +27,7 @@ import org.apache.unomi.api.Persona;
import org.apache.unomi.api.PersonaSession;
import org.apache.unomi.api.PersonaWithSessions;
import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.ProfileAlias;
import org.apache.unomi.api.PropertyMergeStrategyExecutor;
import org.apache.unomi.api.PropertyMergeStrategyType;
import org.apache.unomi.api.PropertyType;
@@ -68,6 +69,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TimerTask;
import java.util.TreeSet;
@@ -546,6 +548,10 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
}
public Profile load(String profileId) {
+ ProfileAlias profileAlias = persistenceService.load(profileId, ProfileAlias.class);
+ if (profileAlias != null) {
+ profileId = profileAlias.getProfileID();
+ }
return persistenceService.load(profileId, Profile.class);
}
@@ -553,6 +559,28 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
return save(profile, forceRefreshOnSave);
}
+ @Override
+ public void addAliasToProfile(String profileID, String alias, String clientID) {
+ ProfileAlias profileAlias = persistenceService.load(alias, ProfileAlias.class);
+
+ if (profileAlias == null) {
+ profileAlias = new ProfileAlias();
+
+ profileAlias.setItemId(alias);
+ profileAlias.setItemType(ProfileAlias.ITEM_TYPE);
+ profileAlias.setProfileID(profileID);
+ profileAlias.setClientID(clientID);
+
+ Date creationTime = new Date();
+ profileAlias.setCreationTime(creationTime);
+ profileAlias.setModifiedTime(creationTime);
+
+ persistenceService.save(profileAlias);
+ } else if (!Objects.equals(profileAlias.getProfileID(), profileID)) {
+ throw new IllegalArgumentException("Alias \"" + alias + "\" already used by profile with ID = \"" + profileID + "\"");
+ }
+ }
+
private Profile save(Profile profile, boolean forceRefresh) {
if (profile.getItemId() == null) {
return null;