diff --git a/Documentation/api-reference.md b/Documentation/api-reference.md index 48310377..28610439 100644 --- a/Documentation/api-reference.md +++ b/Documentation/api-reference.md @@ -38,11 +38,6 @@ String extensionVersion = Identity.extensionVersion(); #### Kotlin -##### Syntax -```kotlin -fun extensionVersion(): String -``` - ##### Example ```kotlin val extensionVersion = Identity.extensionVersion() @@ -77,11 +72,6 @@ Identity.getExperienceCloudId(new AdobeCallback() { #### Kotlin -##### Syntax -```kotlin -fun getExperienceCloudId(callback: AdobeCallback) -``` - ##### Example ```kotlin Identity.getExperienceCloudId { id -> @@ -118,11 +108,6 @@ Identity.getIdentities(new AdobeCallback() { #### Kotlin -##### Syntax -```kotlin -fun getIdentities(callback: AdobeCallback) -``` - ##### Example ```kotlin Identity.getIdentities { identityMap -> @@ -170,11 +155,6 @@ Identity.getUrlVariables(new AdobeCallback() { #### Kotlin -##### Syntax -```kotlin -fun getUrlVariables(callback: AdobeCallback) -``` - ##### Example ```kotlin Identity.getUrlVariables { urlVariablesString -> @@ -214,11 +194,6 @@ Identity.registerExtension(); #### Kotlin -##### Syntax -```kotlin -fun registerExtension() -``` - ##### Example ```kotlin Identity.registerExtension() @@ -253,11 +228,6 @@ Identity.removeIdentity(item, "Email"); #### Kotlin -##### Syntax -```kotlin -fun removeIdentity(item: IdentityItem, namespace: String) -``` - ##### Example ```kotlin val item = IdentityItem("user@example.com") @@ -360,12 +330,6 @@ public void onResume() { #### Kotlin -##### Syntax -```kotlin -public fun setAdvertisingIdentifier(advertisingIdentifier: String) -``` -- _advertisingIdentifier_ is an ID string that provides developers with a simple, standard system to continue to track ads throughout their apps. - ##### Example
import ... @@ -452,14 +416,8 @@ identityMap.addItem(item, "Email") Identity.updateIdentities(identityMap); ``` - #### Kotlin -##### Syntax -```kotlin -fun updateIdentities(identityMap: IdentityMap) -``` - ##### Example ```kotlin val item = IdentityItem("user@example.com") @@ -474,9 +432,9 @@ Identity.updateIdentities(identityMap) ### IdentityMap -Defines a map containing a set of end user identities, keyed on either namespace integration code or the namespace ID of the identity. The values of the map are an array, meaning that more than one identity of each namespace may be carried. +Defines a map containing a set of end user identities, keyed on either namespace integration code or the namespace ID of the identity. The values of the map are an array of [`IdentityItem`](#identityitem)s, meaning that more than one identity of each namespace may be carried. Each `IdentityItem` should have a valid, non-null and non-empty identifier, otherwise it will be ignored. -The format of the IdentityMap class is defined by the [XDM Identity Map Schema](https://github.com/adobe/xdm/blob/master/docs/reference/mixins/shared/identitymap.schema.md). +The format of the `IdentityMap` class is defined by the [XDM Identity Map Schema](https://github.com/adobe/xdm/blob/master/docs/reference/mixins/shared/identitymap.schema.md). For more information, please read an overview of the [Adobe Experience Platform Identity Service](https://experienceleague.adobe.com/docs/experience-platform/identity/home.html). @@ -565,9 +523,9 @@ val hasNotIdentities = identityMap.isEmpty() ### IdentityItem -Defines an identity to be included in an [IdentityMap](#identitymap). + Defines an identity to be included in an [`IdentityMap`](#identitymap). `IdentityItem`s may not have null or empty identifiers and are ignored when added to an [`IdentityMap`](#identitymap) instance. -The format of the IdentityItem class is defined by the [XDM Identity Item Schema](https://github.com/adobe/xdm/blob/master/docs/reference/datatypes/identityitem.schema.md). + The format of the `IdentityItem` class is defined by the [XDM Identity Item Schema](https://github.com/adobe/xdm/blob/master/docs/reference/datatypes/identityitem.schema.md). **Example** @@ -608,7 +566,7 @@ val primary = item.isPrimary ### AuthenticatedState -Defines the state an [Identity Item](#identityitem) is authenticated for. +Defines the authentication state for an [`IdentityItem`](#identityitem). The possible authenticated states are: @@ -626,13 +584,4 @@ public enum AuthenticatedState { AUTHENTICATED("authenticated"), LOGGED_OUT("loggedOut"); } -``` -#### Kotlin - -```kotlin -enum class AuthenticatedState(val name: String) { - AMBIGUOUS("ambiguous"), - AUTHENTICATED("authenticated"), - LOGGED_OUT("loggedOut") -} ``` \ No newline at end of file diff --git a/Makefile b/Makefile index 81fa030c..ebae615a 100644 --- a/Makefile +++ b/Makefile @@ -71,3 +71,15 @@ ci-publish-staging: clean build-release ci-publish-main: clean build-release (./code/gradlew -p code/${EXTENSION-LIBRARY-FOLDER-NAME} publishReleasePublicationToSonatypeRepository -Prelease) + +# usage: update-version VERSION=9.9.9 CORE-VERSION=8.8.8 +# usage: update-version VERSION=9.9.9 +update-version: + @echo "Updating version to $(VERSION), Core version to $(CORE-VERSION)" + sed -i '' "s/[0-9]*\.[0-9]*\.[0-9]/$(VERSION)/g" ./code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java + sed -i '' "s/\(moduleVersion=\)[0-9]*\.[0-9]*\.[0-9]/\1$(VERSION)/g" ./code/gradle.properties + @if [ -z "$(CORE-VERSION)" ]; then \ + echo "CORE-VERSION was not provided, skipping"; \ + else \ + sed -i '' "s/\(mavenCoreVersion=\)[0-9]*\.[0-9]*\.[0-9]/\1$(CORE-VERSION)/g" ./code/gradle.properties; \ + fi \ No newline at end of file diff --git a/code/app/build.gradle b/code/app/build.gradle index bc005aa9..1cef94c3 100644 --- a/code/app/build.gradle +++ b/code/app/build.gradle @@ -65,7 +65,9 @@ dependencies { implementation "com.adobe.marketing.mobile:core:2.+" implementation 'com.adobe.marketing.mobile:identity:2.+' - implementation 'com.adobe.marketing.mobile:edgeconsent:2.+' + implementation ('com.adobe.marketing.mobile:edgeconsent:2.+') { + transitive = false + } implementation 'com.adobe.marketing.mobile:assurance:2.+' implementation ('com.adobe.marketing.mobile:edge:2.+') { transitive = false diff --git a/code/edgeidentity/build.gradle b/code/edgeidentity/build.gradle index 4e9c5965..b50348d3 100644 --- a/code/edgeidentity/build.gradle +++ b/code/edgeidentity/build.gradle @@ -119,7 +119,9 @@ publishing { url = 'https://developer.adobe.com/client-sdks' licenses { license { - name = 'Adobe Proprietary' + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + distribution = 'repo' } } developers { @@ -225,4 +227,4 @@ tasks.withType(Test) { testLogging { showStandardStreams = true } -} \ No newline at end of file +} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java index eaee7d20..34f8a9d4 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java @@ -14,6 +14,7 @@ import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestHelper; @@ -65,6 +66,28 @@ public void testOnBootUp_LoadsAllIdentitiesFromPreference() throws Exception { Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(12, persistedMap.size()); // 3 for ECID and 3 for secondaryECID + 6 } + + @Test + public void testOnBootUp_LoadsAllIdentitiesFromPreference_ignoresEmptyItems() throws Exception { + // test + setEdgeIdentityPersistence( + createXDMIdentityMap( + new TestItem("ECID", "primaryECID"), + new TestItem("UserId", "JohnDoe"), + new TestItem("UserId", ""), // empty Item id + new TestItem("UserId", null) // null Item id + ) + ); + + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); + + // verify xdm shared state + Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); + assertEquals(6, xdmSharedState.size()); // 3 for ECID and 3 UserId JohnDoe + assertEquals("primaryECID", xdmSharedState.get("identityMap.ECID[0].id")); + assertEquals("JohnDoe", xdmSharedState.get("identityMap.UserId[0].id")); + assertNull(xdmSharedState.get("identityMap.UserId[1].id")); + } // -------------------------------------------------------------------------------------------- // All the other bootUp tests with to ECID is coded in IdentityECIDHandling // -------------------------------------------------------------------------------------------- diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java index d9e9620a..8da1e0d7 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java @@ -363,6 +363,36 @@ public void testGetIdentities() { assertEquals(1, responseMap.getIdentityItemsForNamespace("ECID").size()); } + @Test + public void testGetIdentities_itemWithEmptyId_notAddedToMap() { + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); + + // setup + // update Identities through API + IdentityMap map = new IdentityMap(); + map.addItem(new IdentityItem("primary@email.com"), "Email"); + map.addItem(new IdentityItem("secondary@email.com"), "Email"); + map.addItem(new IdentityItem("zzzyyyxxx"), "UserId"); + map.addItem(new IdentityItem(""), "UserId"); + map.addItem(new IdentityItem("John Doe"), "UserName"); + map.addItem(new IdentityItem(""), "EmptyNamespace"); + Identity.updateIdentities(map); + + // test + Map getIdentitiesResponse = getIdentitiesSync(); + waitForThreads(2000); + + // verify + IdentityMap responseMap = (IdentityMap) getIdentitiesResponse.get( + IdentityTestConstants.GetIdentitiesHelper.VALUE + ); + assertEquals(4, responseMap.getNamespaces().size()); + assertEquals(2, responseMap.getIdentityItemsForNamespace("Email").size()); + assertEquals(1, responseMap.getIdentityItemsForNamespace("UserId").size()); + assertEquals(1, responseMap.getIdentityItemsForNamespace("UserName").size()); + assertEquals(1, responseMap.getIdentityItemsForNamespace("ECID").size()); + } + @Test public void testGetIdentities_nullCallback() { registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java index 08d9e696..23692922 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java @@ -16,7 +16,7 @@ final class IdentityConstants { static final String LOG_TAG = "EdgeIdentity"; static final String EXTENSION_NAME = "com.adobe.edge.identity"; static final String EXTENSION_FRIENDLY_NAME = "Edge Identity"; - static final String EXTENSION_VERSION = "2.0.0"; + static final String EXTENSION_VERSION = "2.0.1"; static final class Default { diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java index e9e2dc64..b324d5c9 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java @@ -37,12 +37,15 @@ public final class IdentityItem { private final boolean primary; /** - * Creates a new {@link IdentityItem} + * Creates a new {@link IdentityItem}. + * An {@code IdentityItem} should not have an empty or null {@code id} value. An {@link IdentityMap} + * will reject {@code IdentityItem}s with null or empty identifiers. + * * * @param id id for the item; should not be null * @param authenticatedState {@link AuthenticatedState} for the item; if none is provided {@link AuthenticatedState#AMBIGUOUS} is used as default * @param primary primary flag for the item - * @throws IllegalArgumentException if id is null + * @throws IllegalArgumentException if {@code id} is null */ public IdentityItem( @NonNull final String id, @@ -62,8 +65,11 @@ public IdentityItem( * Creates a new {@link IdentityItem} with default values * {@code authenticatedState) is set to AMBIGUOUS * (@code primary} is set to false + * An {@code IdentityItem} should not have an empty or null {@code id} value. An {@link IdentityMap} + * will reject {@code IdentityItem}s with null or empty identifiers. * * @param id the id for this {@link IdentityItem}; should not be null + * @throws IllegalArgumentException if {@code id} is null */ public IdentityItem(@NonNull final String id) { this(id, AuthenticatedState.AMBIGUOUS, false); @@ -193,7 +199,15 @@ static IdentityItem fromData(final Map data) { return new IdentityItem(id, authenticatedState, primary); } catch (final DataReaderException e) { Log.debug(LOG_TAG, LOG_SOURCE, "Failed to create IdentityItem from data."); - return null; + } catch (final IllegalArgumentException e) { + Log.debug( + LOG_TAG, + LOG_SOURCE, + "Failed to create IdentityItem from data as 'id' is null. %s", + e.getLocalizedMessage() + ); } + + return null; } } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java index e86d3d94..c0114c33 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java @@ -79,6 +79,7 @@ public List getNamespaces() { /** * Add an identity item which is used to clearly distinguish entities that are interacting * with digital experiences. + * An {@link IdentityItem} with an empty {@code id} is not allowed and is ignored. * * @param item {@link IdentityItem} to be added to the given {@code namespace}; should not be null * @param namespace the namespace integration code or namespace ID of the identity; should not be null @@ -152,6 +153,7 @@ public String toString() { /** * Add an identity item which is used to clearly distinguish entities that are interacting * with digital experiences. + * An {@link IdentityItem} with an empty {@code id} is not allowed and is ignored. * * @param item {@link IdentityItem} to be added to the namespace * @param namespace the namespace integration code or namespace ID of the identity @@ -174,6 +176,7 @@ void addItem(final IdentityItem item, final String namespace, final boolean isFi /** * Merge the given map on to this {@link IdentityMap}. Any {@link IdentityItem} in map which shares the same * namespace and id as an item in this {@code IdentityMap} will replace that {@code IdentityItem}. + * Any {@link IdentityItem}s with an empty {@code id} are not allowed and are ignored. * * @param map {@link IdentityMap} to be merged into this object */ @@ -313,6 +316,16 @@ static IdentityMap fromXDMMap(final Map map) { // ======================================================================================== private void addItemToMap(final IdentityItem newItem, final String namespace, final boolean isFirstItem) { + if (StringUtils.isNullOrEmpty(newItem.getId())) { + Log.debug( + LOG_TAG, + LOG_SOURCE, + "Unable to add IdentityItem to IdentityMap with null or empty identifier value: %s", + newItem + ); + return; + } + // check if namespace exists final List itemList; diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java index 2970d61c..cb76fb4d 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java @@ -17,7 +17,7 @@ import com.adobe.marketing.mobile.util.StringUtils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; class URLUtils { @@ -54,9 +54,10 @@ static String generateURLVariablesPayload(final String ts, final String ecid, fi // No need to encode urlFragment.append("null"); } else { - urlFragment.append(URLEncoder.encode(theIdString, StandardCharsets.UTF_8.toString())); + urlFragment.append(URLEncoder.encode(theIdString, Charset.forName("UTF-8").name())); } - } catch (UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException | IllegalArgumentException e) { + urlFragment.append("null"); Log.debug(LOG_TAG, LOG_SOURCE, String.format("Failed to encode urlVariable string: %s", e)); } return urlFragment.toString(); diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityItemTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityItemTests.java index 1c6c760e..ce04e32e 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityItemTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityItemTests.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.HashMap; @@ -36,12 +37,33 @@ public void testIdentityItem_toObjectMap_full() { } @Test(expected = IllegalArgumentException.class) - public void testIdentityItem_toObjectMap_missingId() { - // setup + public void testIdentityItem_ctor1_nullId_throwsIllegalArgumentException() { IdentityItem item = new IdentityItem(null, AuthenticatedState.AUTHENTICATED, true); + } - // test - Map data = item.toObjectMap(); + @Test + public void testIdentityItem_ctor1_emptyId() { + IdentityItem item = new IdentityItem("", AuthenticatedState.AUTHENTICATED, true); + + // For backward compatibility, an IdentityItem can contain empty identifiers. + assertEquals("", item.getId()); + assertEquals("authenticated", item.getAuthenticatedState().getName()); + assertTrue(item.isPrimary()); + } + + @Test(expected = IllegalArgumentException.class) + public void testIdentityItem_ctor2_nullId_throwsIllegalArgumentException() { + IdentityItem item = new IdentityItem((String) null); + } + + @Test + public void testIdentityItem_ctor2_emptyId() { + IdentityItem item = new IdentityItem(""); + + // For backward compatibility, an IdentityItem can contain empty identifiers. + assertEquals("", item.getId()); + assertEquals("ambiguous", item.getAuthenticatedState().getName()); + assertFalse(item.isPrimary()); } @Test @@ -107,6 +129,43 @@ public void testIdentityItem_fromData_missingPrimary() { assertEquals(false, item.isPrimary()); } + @Test + public void testIdentityItem_fromData_missingId_returnNull() { + // setup + Map map = new HashMap<>(); + map.put("authenticatedState", "loggedOut"); + map.put("primary", false); + + assertNull(IdentityItem.fromData(map)); + } + + @Test + public void testIdentityItem_fromData_nullId_returnNull() { + // setup + Map map = new HashMap<>(); + map.put("id", null); + map.put("authenticatedState", "loggedOut"); + map.put("primary", false); + + assertNull(IdentityItem.fromData(map)); + } + + @Test + public void testIdentityItem_fromData_emptyId() { + // setup + Map map = new HashMap<>(); + map.put("id", ""); + map.put("authenticatedState", "loggedOut"); + map.put("primary", false); + + IdentityItem item = IdentityItem.fromData(map); + + // For backward compatibility, an IdentityItem can contain empty identifiers. + assertEquals("", item.getId()); + assertEquals("loggedOut", item.getAuthenticatedState().getName()); + assertFalse(item.isPrimary()); + } + @Test public void testIdentityItem_isEqualShouldReturnTrue() { IdentityItem item1 = new IdentityItem("id", AuthenticatedState.AMBIGUOUS, false); diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java index 06ff453b..75f2160c 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java @@ -34,6 +34,14 @@ public void test_AddItem() { IdentityTestUtil.flattenMap(map.asXDMMap(false)).get("identityMap.location[0].id"); } + @Test + public void test_addItem_withEmptyID_notAdded() { + // test + IdentityMap map = new IdentityMap(); + map.addItem(new IdentityItem(""), "location"); + assertTrue(map.isEmpty()); + } + @Test public void test_AddItem_InvalidInputs() { // test @@ -310,6 +318,83 @@ public void test_FromData() throws Exception { assertEquals("false", flattenedMap.get("identityMap.USERID[0].primary")); } + @Test + public void test_FromData_removesItem_emptyId() throws Exception { + // setup + final String jsonStr = + "{\n" + + " \"identityMap\": {\n" + + " \"ECID\": [\n" + + " {\n" + + " \"id\":randomECID,\n" + + " \"authenticatedState\": \"ambiguous\",\n" + + " \"primary\": true\n" + + " }\n" + + " ],\n" + + " \"USERID\": [\n" + + " {\n" + + " \"id\":\"\",\n" + + " \"authenticatedState\": \"authenticated\",\n" + + " \"primary\": false\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + + // test + IdentityMap map = IdentityMap.fromXDMMap(xdmData); + + // verify + Map flattenedMap = IdentityTestUtil.flattenMap(map.asXDMMap(false)); + assertEquals("randomECID", flattenedMap.get("identityMap.ECID[0].id")); + assertEquals("ambiguous", flattenedMap.get("identityMap.ECID[0].authenticatedState")); + assertEquals("true", flattenedMap.get("identityMap.ECID[0].primary")); + assertNull(flattenedMap.get("identityMap.USERID[0].id")); + assertNull(flattenedMap.get("identityMap.USERID[0].authenticatedState")); + assertNull(flattenedMap.get("identityMap.USERID[0].primary")); + } + + @Test + public void test_FromData_removesItem_missingId() throws Exception { + // setup + final String jsonStr = + "{\n" + + " \"identityMap\": {\n" + + " \"ECID\": [\n" + + " {\n" + + " \"id\":randomECID,\n" + + " \"authenticatedState\": \"ambiguous\",\n" + + " \"primary\": true\n" + + " }\n" + + " ],\n" + + " \"USERID\": [\n" + + " {\n" + + " \"authenticatedState\": \"authenticated\",\n" + + " \"primary\": false\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + + // test + IdentityMap map = IdentityMap.fromXDMMap(xdmData); + + // verify + Map flattenedMap = IdentityTestUtil.flattenMap(map.asXDMMap(false)); + assertEquals("randomECID", flattenedMap.get("identityMap.ECID[0].id")); + assertEquals("ambiguous", flattenedMap.get("identityMap.ECID[0].authenticatedState")); + assertEquals("true", flattenedMap.get("identityMap.ECID[0].primary")); + assertNull(flattenedMap.get("identityMap.USERID[0].id")); + assertNull(flattenedMap.get("identityMap.USERID[0].authenticatedState")); + assertNull(flattenedMap.get("identityMap.USERID[0].primary")); + } + @Test public void testFromXDMMap_NullAndEmptyData() { assertNull(IdentityMap.fromXDMMap(null)); diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java index 425d0627..991bc974 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java @@ -175,6 +175,30 @@ public void testConstruct_FromXDMData_NothingFromPersistence() { assertEquals(0, flattenMap(props.toXDMData(false)).size()); } + @Test + public void testConstruct_FromXDMData_removesInvalidIdentityItems() { + // setup, Items with null or empty ids are invalid + Map persistedIdentifiers = createXDMIdentityMap( + new TestItem("UserId", "secretID"), + new TestItem("InvalidEmpty", ""), + new TestItem("InvalidNull", null), + new TestECIDItem("primaryECID"), + new TestECIDItem("secondaryECID") + ); + + // test + IdentityProperties props = new IdentityProperties(persistedIdentifiers); + + // verify + Map flatMap = flattenMap(props.toXDMData(false)); + assertEquals(9, flatMap.size()); // 3x3 + assertEquals("primaryECID", props.getECID().toString()); + assertEquals("secondaryECID", props.getECIDSecondary().toString()); + assertEquals("secretID", flatMap.get("identityMap.UserId[0].id")); + assertNull(flatMap.get("identityMap.InvalidEmpty[0].id")); + assertNull(flatMap.get("identityMap.InvalidNull[0].id")); + } + // ====================================================================================================================== // Tests for method : setECID(final ECID newEcid) // ====================================================================================================================== diff --git a/code/gradle.properties b/code/gradle.properties index 36ce6cc2..067e76e1 100644 --- a/code/gradle.properties +++ b/code/gradle.properties @@ -8,7 +8,7 @@ android.disableAutomaticComponentCreation=true moduleProjectName=edgeidentity moduleName=edgeidentity moduleAARName=edgeidentity-phone-release.aar -moduleVersion=2.0.0 +moduleVersion=2.0.1 mavenRepoName=AdobeMobileEdgeIdentitySdk mavenRepoDescription=Adobe Experience Platform Edge Identity extension for the Adobe Experience Platform Mobile SDK