diff --git a/sdk/communication/azure-communication-common/CHANGELOG.md b/sdk/communication/azure-communication-common/CHANGELOG.md index 01f43693d0..10c392c24e 100644 --- a/sdk/communication/azure-communication-common/CHANGELOG.md +++ b/sdk/communication/azure-communication-common/CHANGELOG.md @@ -1,5 +1,11 @@ # Release History +## 1.3.0 (2025-03-12) + +### Features Added +- Added support for a new communication identifier `TeamsExtensionUserIdentifier` which maps rawIds with format `8:acs:{resourceId}_{tenantId}_{userId}`. +- Added `isAnonymous` and `getAssertedId` methods to `PhoneNumberIdentifier`. + ## 1.2.1 (2024-02-23) ### Other Changes diff --git a/sdk/communication/azure-communication-common/README.md b/sdk/communication/azure-communication-common/README.md index 53864e18f7..9f40d4989e 100644 --- a/sdk/communication/azure-communication-common/README.md +++ b/sdk/communication/azure-communication-common/README.md @@ -20,7 +20,7 @@ This package contains common code for Azure Communication Service libraries. APIs that would require the Java 8+ API desugaring provided by Android Gradle plugin 4.0.0. ### Versions available -The current version of this library is **1.2.1**. +The current version of this library is **1.3.0**. ### Install the library To install the Azure client libraries for Android, add them as dependencies within your @@ -36,13 +36,13 @@ Add an `implementation` configuration to the `dependencies` block of your app's // build.gradle dependencies { ... - implementation "com.azure.android:azure-communication-common:1.2.1" + implementation "com.azure.android:azure-communication-common:1.3.0" } // build.gradle.kts dependencies { ... - implementation("com.azure.android:azure-communication-common:1.2.1") + implementation("com.azure.android:azure-communication-common:1.3.0") } ``` @@ -53,7 +53,7 @@ To import the library into your project using the [Maven](https://maven.apache.o com.azure.android azure-communication-common - 1.2.1 + 1.3.0 ``` diff --git a/sdk/communication/azure-communication-common/gradle.properties b/sdk/communication/azure-communication-common/gradle.properties index 2d48fba979..78d97e4245 100644 --- a/sdk/communication/azure-communication-common/gradle.properties +++ b/sdk/communication/azure-communication-common/gradle.properties @@ -1 +1 @@ -version=1.2.1 +version=1.3.0 diff --git a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/CommunicationIdentifier.java b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/CommunicationIdentifier.java index c937426c19..32cfdb4584 100644 --- a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/CommunicationIdentifier.java +++ b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/CommunicationIdentifier.java @@ -28,9 +28,7 @@ public abstract class CommunicationIdentifier { * @throws IllegalArgumentException raw id is null or empty. */ public static CommunicationIdentifier fromRawId(String rawId) { - if (rawId == null || rawId.trim().length() == 0) { - throw new IllegalArgumentException("The parameter [rawId] cannot be null to empty."); - } + ValidationUtils.validateNotNullOrEmpty(rawId, "rawId"); if (rawId.startsWith(PHONE_NUMBER_PREFIX)) { return new PhoneNumberIdentifier(rawId.substring(PHONE_NUMBER_PREFIX.length())); @@ -60,11 +58,12 @@ public static CommunicationIdentifier fromRawId(String rawId) { return new MicrosoftTeamsAppIdentifier(suffix, CommunicationCloudEnvironment.DOD); case TEAMS_APP_GCCH_CLOUD_PREFIX: return new MicrosoftTeamsAppIdentifier(suffix, CommunicationCloudEnvironment.GCCH); - case ACS_USER_PREFIX: case SPOOL_USER_PREFIX: + return new CommunicationUserIdentifier(rawId); + case ACS_USER_PREFIX: case ACS_USER_DOD_CLOUD_PREFIX: case ACS_USER_GCCH_CLOUD_PREFIX: - return new CommunicationUserIdentifier(rawId); + return tryCreateTeamsExtensionUserOrCommunicationUser(prefix, suffix, rawId); default: return new UnknownIdentifier(rawId); } @@ -110,4 +109,38 @@ public boolean equals(Object that) { public int hashCode() { return getRawId().hashCode(); } + + private static CommunicationIdentifier tryCreateTeamsExtensionUserOrCommunicationUser(String prefix, String suffix, + String rawId) { + String[] segments = suffix.split("_"); + if (segments.length != 3) { + return new CommunicationUserIdentifier(rawId); + } + + String resourceId = segments[0]; + String tenantId = segments[1]; + String userId = segments[2]; + CommunicationCloudEnvironment cloud = determineCloudEnvironment(prefix); + + return new TeamsExtensionUserIdentifier(userId, tenantId, resourceId).setCloudEnvironment(cloud); + } + + /** + * Determine the cloud based on identifier prefix. + * @param cloudPrefix . + * @return CommunicationCloudEnvironment. + * @throws IllegalArgumentException thrown if CommunicationCloudEnvironment cannot be initialized. + */ + static CommunicationCloudEnvironment determineCloudEnvironment(String cloudPrefix) { + switch (cloudPrefix) { + case ACS_USER_DOD_CLOUD_PREFIX: + return CommunicationCloudEnvironment.DOD; + case ACS_USER_GCCH_CLOUD_PREFIX: + return CommunicationCloudEnvironment.GCCH; + case ACS_USER_PREFIX: + return CommunicationCloudEnvironment.PUBLIC; + default: + throw new IllegalArgumentException("Cannot initialize CommunicationCloudEnvironment."); + } + } } diff --git a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/MicrosoftTeamsUserIdentifier.java b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/MicrosoftTeamsUserIdentifier.java index a6264f8d0d..9f1becab57 100644 --- a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/MicrosoftTeamsUserIdentifier.java +++ b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/MicrosoftTeamsUserIdentifier.java @@ -16,7 +16,7 @@ public final class MicrosoftTeamsUserIdentifier extends CommunicationIdentifier * Creates a MicrosoftTeamsUserIdentifier object * * @param userId Id of the Microsoft Teams user. If the user isn't anonymous, - * the id is the AAD object id of the user. + * the id is the Entra ID object id of the user. * @param isAnonymous set this to true if the user is anonymous, * for example when joining a meeting with a share link * @throws IllegalArgumentException thrown if userId parameter fail the validation. @@ -34,7 +34,7 @@ public MicrosoftTeamsUserIdentifier(String userId, boolean isAnonymous) { * Creates a MicrosoftTeamsUserIdentifier object * * @param userId Id of the Microsoft Teams user. If the user isn't anonymous, - * the id is the AAD object id of the user. + * the id is the Entra ID object id of the user. * @throws IllegalArgumentException thrown if userId parameter fail the validation. */ public MicrosoftTeamsUserIdentifier(String userId) { diff --git a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/PhoneNumberIdentifier.java b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/PhoneNumberIdentifier.java index 1429d7bfaf..59cd4a63b7 100644 --- a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/PhoneNumberIdentifier.java +++ b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/PhoneNumberIdentifier.java @@ -6,7 +6,11 @@ * Communication identifier for Communication Services Phone Numbers */ public final class PhoneNumberIdentifier extends CommunicationIdentifier { + private static final String ANONYMOUS = "anonymous"; private final String phoneNumber; + private String assertedId; + + private boolean isAnonymous; /** * Creates a PhoneNumberIdentifier object @@ -16,10 +20,7 @@ public final class PhoneNumberIdentifier extends CommunicationIdentifier { * @throws IllegalArgumentException thrown if phoneNumber parameter fail the validation. */ public PhoneNumberIdentifier(String phoneNumber) { - if (phoneNumber == null || phoneNumber.trim().length() == 0) { - throw new IllegalArgumentException("The initialization parameter [phoneNumber] cannot be null to empty."); - } - this.phoneNumber = phoneNumber; + this.phoneNumber = ValidationUtils.validateNotNullOrEmpty(phoneNumber, "phoneNumber"); this.setRawId(PHONE_NUMBER_PREFIX + phoneNumber); } @@ -30,6 +31,35 @@ public String getPhoneNumber() { return phoneNumber; } + /** + * Checks if the phone number is anonymous, e.g., used to represent a hidden caller ID. + * + * @return true if the phone number is anonymous, false otherwise. + */ + public boolean isAnonymous() { + return isAnonymous; + } + + /** + * Gets the asserted ID for the phone number, distinguishing it from other connections made through the same number. + * + * @return the string identifier representing the asserted ID for the phone number. + */ + public String getAssertedId() { + if (assertedId != null && !assertedId.trim().isEmpty()) { + return assertedId; + } + + String[] segments = getRawId().substring(PHONE_NUMBER_PREFIX.length()).split("_"); + if (segments.length > 1) { + assertedId = segments[segments.length - 1]; + return assertedId; + } + + assertedId = ""; + return null; + } + /** * Set full id of the identifier * RawId is the encoded format for identifiers to store in databases or as stable keys in general. @@ -40,6 +70,7 @@ public String getPhoneNumber() { @Override public PhoneNumberIdentifier setRawId(String rawId) { super.setRawId(rawId); + isAnonymous = getRawId().equals(PHONE_NUMBER_PREFIX + ANONYMOUS); return this; } diff --git a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/TeamsExtensionUserIdentifier.java b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/TeamsExtensionUserIdentifier.java new file mode 100644 index 0000000000..97772f328e --- /dev/null +++ b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/TeamsExtensionUserIdentifier.java @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.android.communication.common; + +/** + * Communication identifier for Microsoft Teams Phone user who is using a Communication Services resource + * to extend their Teams Phone set up. + */ +public final class TeamsExtensionUserIdentifier extends CommunicationIdentifier { + + private final String userId; + + private final String tenantId; + + private final String resourceId; + + private CommunicationCloudEnvironment cloudEnvironment; + + /** + * Creates a TeamsExtensionUserIdentifier object with PUBLIC cloud environment. + * + * @param userId ID of the Microsoft Teams Extension user i.e. the Entra ID object id of the user. + * @param tenantId Tenant ID of the Microsoft Teams Extension user. + * @param resourceId The Communication Services resource id. + * @throws IllegalArgumentException if any parameter fail the validation. + */ + public TeamsExtensionUserIdentifier(String userId, String tenantId, String resourceId) { + this.userId = ValidationUtils.validateNotNullOrEmpty(userId, "userId"); + this.tenantId = ValidationUtils.validateNotNullOrEmpty(tenantId, "tenantId"); + this.resourceId = ValidationUtils.validateNotNullOrEmpty(resourceId, "resourceId"); + this.cloudEnvironment = CommunicationCloudEnvironment.PUBLIC; + + generateRawId(); + } + + /** + * Set full ID of the identifier + * RawId is the encoded format for identifiers to store in databases or as stable keys in general. + * + * @param rawId full ID of the identifier. + * @return TeamsExtensionUserIdentifier object itself. + */ + @Override + public TeamsExtensionUserIdentifier setRawId(String rawId) { + super.setRawId(rawId); + return this; + } + + /** + * Get Microsoft Teams Extension user + * @return ID of the Microsoft Teams Extension user i.e. the Entra ID object id of the user. + */ + public String getUserId() { + return userId; + } + + /** + * Get Microsoft Teams Extension user Tenant ID + * @return Tenant ID of the Microsoft Teams Extension user. + */ + public String getTenantId() { + return tenantId; + } + + /** + * Get Communication Services resource id. + * @return the Communication Services resource id. + */ + public String getResourceId() { + return resourceId; + } + + /** + * Get cloud environment of the Teams Extension User identifier + * @return cloud environment in which this identifier is created + */ + public CommunicationCloudEnvironment getCloudEnvironment() { + return cloudEnvironment; + } + + /** + * Set cloud environment of the Teams Extension User identifier + * + * @param cloudEnvironment the cloud environment in which this identifier is created + * @return this object + * @throws IllegalArgumentException if cloudEnvironment . + * + */ + public TeamsExtensionUserIdentifier setCloudEnvironment(CommunicationCloudEnvironment cloudEnvironment) { + this.cloudEnvironment = ValidationUtils.validateNotNull(cloudEnvironment, "cloudEnvironment"); + generateRawId(); + return this; + } + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + + if (!(that instanceof TeamsExtensionUserIdentifier)) { + return false; + } + + return super.equals(that); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + private void generateRawId() { + String identifierBase = this.resourceId + "_" + this.tenantId + "_" + this.userId; + if (cloudEnvironment.equals(CommunicationCloudEnvironment.DOD)) { + super.setRawId(ACS_USER_DOD_CLOUD_PREFIX + identifierBase); + } else if (cloudEnvironment.equals(CommunicationCloudEnvironment.GCCH)) { + super.setRawId(ACS_USER_GCCH_CLOUD_PREFIX + identifierBase); + } else { + super.setRawId(ACS_USER_PREFIX + identifierBase); + } + } +} diff --git a/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/ValidationUtils.java b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/ValidationUtils.java new file mode 100644 index 0000000000..62cf75bc87 --- /dev/null +++ b/sdk/communication/azure-communication-common/src/main/java/com/azure/android/communication/common/ValidationUtils.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.android.communication.common; + +class ValidationUtils { + + /** + * Validate string + * @param value a value to be validated + * @param paramName Parameter name for exceptionMessage + * @return value + * + * @throws IllegalArgumentException when value is null or Empty. + */ + public static String validateNotNullOrEmpty(String value, String paramName) { + if (value == null || value.trim().isEmpty()) { + String message = "The parameter [" + paramName + "] cannot be null or empty."; + throw new IllegalArgumentException(message); + } + return value; + } + + /** + * Validate string + * @param cloudEnvironment a value to be validated + * @param paramName Parameter name for exceptionMessage + * @return value + * + * @throws IllegalArgumentException when value is null or Empty. + */ + public static CommunicationCloudEnvironment validateNotNull(CommunicationCloudEnvironment cloudEnvironment, + String paramName) { + if (cloudEnvironment == null) { + String message = "The parameter [" + paramName + "] cannot be null."; + throw new IllegalArgumentException(message); + } + return cloudEnvironment; + } + +} diff --git a/sdk/communication/azure-communication-common/src/test/java/com/azure/android/communication/common/CommunicationIdentifierTests.java b/sdk/communication/azure-communication-common/src/test/java/com/azure/android/communication/common/CommunicationIdentifierTests.java index 1cfc69eefd..a94058582b 100644 --- a/sdk/communication/azure-communication-common/src/test/java/com/azure/android/communication/common/CommunicationIdentifierTests.java +++ b/sdk/communication/azure-communication-common/src/test/java/com/azure/android/communication/common/CommunicationIdentifierTests.java @@ -4,24 +4,48 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class CommunicationIdentifierTests { - private final String userId = "user id"; - private String microsoftTeamsAppId = "45ab2481-1c1c-4005-be24-0ffb879b1130"; - private final String fullId = "some lengthy id string"; + private final String microsoftTeamsAppId = "45ab2481-1c1c-4005-be24-0ffb879b1130"; + private final String userId = "c1a6f4d2-8b39-4e88-bef2-9b2d8d685d3c"; + private final String tenantId= "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d"; + private final String resourceId= "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37"; @Test - public void defaultCloudIsPublicForMicrosoftTeamsUserIdentifier() { + public void exceptionThrownForNullOrEmptyParameters() { + assertThrows(IllegalArgumentException.class, () -> new CommunicationUserIdentifier("")); + assertThrows(IllegalArgumentException.class, () -> new MicrosoftTeamsUserIdentifier("")); + assertThrows(IllegalArgumentException.class, () -> new PhoneNumberIdentifier("")); + assertThrows(IllegalArgumentException.class, () -> new MicrosoftTeamsAppIdentifier("")); + assertThrows(IllegalArgumentException.class, () -> new TeamsExtensionUserIdentifier("", "", "")); + + assertThrows(IllegalArgumentException.class, () -> new CommunicationUserIdentifier(null)); + assertThrows(IllegalArgumentException.class, () -> new MicrosoftTeamsUserIdentifier(null)); + assertThrows(IllegalArgumentException.class, () -> new PhoneNumberIdentifier(null)); + assertThrows(IllegalArgumentException.class, () -> new MicrosoftTeamsAppIdentifier(null)); + assertThrows(IllegalArgumentException.class, () -> new TeamsExtensionUserIdentifier(null, "b", "c")); + assertThrows(IllegalArgumentException.class, () -> new TeamsExtensionUserIdentifier("a", null, "c")); + assertThrows(IllegalArgumentException.class, () -> new TeamsExtensionUserIdentifier("a", "b", null)); + } + + @Test + public void defaultCloudIsPublicForAllIdentifiers() { + assertEquals(CommunicationCloudEnvironment.PUBLIC, + new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", true).getCloudEnvironment()); assertEquals(CommunicationCloudEnvironment.PUBLIC, - new MicrosoftTeamsUserIdentifier(userId, true).setRawId(fullId).getCloudEnvironment()); + new MicrosoftTeamsAppIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130").getCloudEnvironment()); + assertEquals(CommunicationCloudEnvironment.PUBLIC, + new TeamsExtensionUserIdentifier("207ffef6-9444-41fb-92ab-20eacaae2768", "45ab2481-1c1c-4005-be24-0ffb879b1130", "bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd").getCloudEnvironment()); } @Test - public void microsoftTeamsAppIdentifier_throwsMicrosofTeamsAppIdNullOrEmpty() { + public void microsoftTeamsAppIdentifier_throwsMicrosoftTeamsAppIdNullOrEmpty() { IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, () -> new MicrosoftTeamsAppIdentifier(null)); assertEquals("The initialization parameter [appId] cannot be null or empty.", illegalArgumentException.getMessage()); @@ -29,12 +53,6 @@ public void microsoftTeamsAppIdentifier_throwsMicrosofTeamsAppIdNullOrEmpty() { assertEquals("The initialization parameter [appId] cannot be null or empty.", illegalArgumentException.getMessage()); } - @Test - public void microsoftTeamsAppIdentifier_defaultCloudIsPublic() { - assertEquals(CommunicationCloudEnvironment.PUBLIC, - new MicrosoftTeamsAppIdentifier(userId).getCloudEnvironment()); - } - @Test public void microsoftTeamsAppIdentifier_cloudEnvironmentIsConsideredInEqualityCheck() { assertEquals(new MicrosoftTeamsAppIdentifier(microsoftTeamsAppId), @@ -90,6 +108,113 @@ public void microsoftTeamsUserIdentifier_rawIdTakesPrecedenceInEqualityCheck() { .setCloudEnvironment(CommunicationCloudEnvironment.GCCH).setRawId("test raw id")); } + @Test + public void TeamsExtensionIdentifier_rawIdTakesPrecedenceInEqualityCheck() { + // Public Cloud + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC), + new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); + + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC) + .setRawId("Raw Id"), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC) + .setRawId("AnotherRaw Id")); + String TeamsPhoneIdentifierBase = this.resourceId + "_" + this.tenantId + "_" + this.userId; + String rawId = "8:acs:" + TeamsPhoneIdentifierBase; + assertEquals( new TeamsExtensionUserIdentifier("override", tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.PUBLIC) + .setRawId(rawId), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); + + assertEquals( new TeamsExtensionUserIdentifier("override", tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC) + .setRawId(rawId), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId)); + + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.PUBLIC), + new TeamsExtensionUserIdentifier("override", tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.PUBLIC) + .setRawId(rawId)); + + // GCCH + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.GCCH), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment(CommunicationCloudEnvironment.GCCH)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.GCCH), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.PUBLIC)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.GCCH) + .setRawId("Raw Id"), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.GCCH) + .setRawId("AnotherRaw Id")); + + rawId = "8:gcch-acs:" + TeamsPhoneIdentifierBase; + assertEquals( new TeamsExtensionUserIdentifier("override", tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.GCCH) + .setRawId(rawId), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment(CommunicationCloudEnvironment.GCCH)); + + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.GCCH), + new TeamsExtensionUserIdentifier("override", tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.GCCH) + .setRawId(rawId)); + + // DOD + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.DOD), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.DOD)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.DOD), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.PUBLIC)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.DOD), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.GCCH)); + + assertNotEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.DOD) + .setRawId("Raw Id"), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.DOD) + .setRawId("AnotherRaw Id")); + + rawId = "8:dod-acs:" + TeamsPhoneIdentifierBase; + assertEquals( new TeamsExtensionUserIdentifier("override", tenantId, resourceId) + .setCloudEnvironment( CommunicationCloudEnvironment.DOD) + .setRawId(rawId), + new TeamsExtensionUserIdentifier(userId, tenantId, + resourceId).setCloudEnvironment( CommunicationCloudEnvironment.DOD)); + + assertEquals( new TeamsExtensionUserIdentifier(userId, tenantId, resourceId) + .setCloudEnvironment(CommunicationCloudEnvironment.DOD), + new TeamsExtensionUserIdentifier("override", tenantId, + resourceId).setCloudEnvironment(CommunicationCloudEnvironment.DOD) + .setRawId(rawId)); + } + @Test public void phoneNumberIdentifier_rawIdTakesPrecedenceInEqualityCheck() { assertEquals(new PhoneNumberIdentifier("+14255550123"), new PhoneNumberIdentifier("+14255550123")); @@ -102,12 +227,76 @@ public void phoneNumberIdentifier_rawIdTakesPrecedenceInEqualityCheck() { new PhoneNumberIdentifier("+override").setRawId("4:+14255550123")); } + @Test + public void phoneNumberIdentifier_getParametersCheck() { + assertFalse(new PhoneNumberIdentifier("14255550123").isAnonymous()); + assertTrue(new PhoneNumberIdentifier("anonymous").isAnonymous()); + assertTrue(new PhoneNumberIdentifier("14255550123").setRawId("4:anonymous").isAnonymous()); + assertFalse(new PhoneNumberIdentifier("anonymous").setRawId("14255550123").isAnonymous()); + + assertNull(new PhoneNumberIdentifier("14255550121").getAssertedId()); + assertNull(new PhoneNumberIdentifier("14255550121.123").getAssertedId()); + assertNull(new PhoneNumberIdentifier("14255550121-123").getAssertedId()); + assertEquals("123", new PhoneNumberIdentifier("14255550121_123").getAssertedId()); + assertEquals("456", new PhoneNumberIdentifier("14255550121_123_456").getAssertedId()); + + // Ensure getAssertedId() returns the same value on repeated calls + PhoneNumberIdentifier staticPhoneNumberIdentifier = new PhoneNumberIdentifier("14255550121_123"); + assertEquals("123", staticPhoneNumberIdentifier.getAssertedId()); + assertEquals("123", staticPhoneNumberIdentifier.getAssertedId()); + } + + @Test + public void teamsExtensionUserIdentifier_getParametersCheck() + { + TeamsExtensionUserIdentifier identifier = new TeamsExtensionUserIdentifier(userId, tenantId, resourceId); + + assertEquals(identifier.getResourceId(), resourceId); + assertEquals(identifier.getTenantId(), tenantId); + assertEquals(identifier.getUserId(), userId); + assertEquals(identifier.getCloudEnvironment(), CommunicationCloudEnvironment.PUBLIC); + } + + @Test + public void teamsExtensionUserIdentifier_SetCloudEnvironment_NullValue() + { + TeamsExtensionUserIdentifier identifier = new TeamsExtensionUserIdentifier(userId, tenantId, resourceId); + assertThrows(IllegalArgumentException.class, () -> identifier.setCloudEnvironment(null)); + } + + @Test + public void teamsExtensionUserIdentifier_getParametersCheck_DOD() + { + CommunicationCloudEnvironment cloudEnvironment = CommunicationCloudEnvironment.DOD; + + TeamsExtensionUserIdentifier identifier = new TeamsExtensionUserIdentifier(userId, tenantId, resourceId).setCloudEnvironment(cloudEnvironment); + + assertEquals(identifier.getResourceId(), resourceId); + assertEquals(identifier.getTenantId(), tenantId); + assertEquals(identifier.getUserId(), userId); + assertEquals(identifier.getCloudEnvironment(), cloudEnvironment); + } + + @Test + public void teamsExtensionUserIdentifier_getParametersCheck_GCCH() + { + CommunicationCloudEnvironment cloudEnvironment = CommunicationCloudEnvironment.GCCH; + + TeamsExtensionUserIdentifier identifier = new TeamsExtensionUserIdentifier(userId, tenantId, resourceId).setCloudEnvironment(cloudEnvironment); + + assertEquals(identifier.getResourceId(), resourceId); + assertEquals(identifier.getTenantId(), tenantId); + assertEquals(identifier.getUserId(), userId); + assertEquals(identifier.getCloudEnvironment(), cloudEnvironment); + } + @Test public void getRawIdOfIdentifier() { assertRawId(new CommunicationUserIdentifier("8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130"), "8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new CommunicationUserIdentifier("8:gcch-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130"), "8:gcch-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new CommunicationUserIdentifier("someFutureFormat"), "someFutureFormat"); + assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130"), "8:orgid:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130"), "8:orgid:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130").setCloudEnvironment(CommunicationCloudEnvironment.DOD), "8:dod:45ab2481-1c1c-4005-be24-0ffb879b1130"); @@ -115,6 +304,14 @@ public void getRawIdOfIdentifier() assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", false), "8:orgid:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", true), "8:teamsvisitor:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRawId(new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", true).setRawId("8:orgid:legacyFormat"), "8:orgid:legacyFormat"); + + assertRawId(new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC), + "8:acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRawId(new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.DOD), + "8:dod-acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRawId(new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.GCCH), + "8:gcch-acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRawId(new PhoneNumberIdentifier("+112345556789"), "4:+112345556789"); assertRawId(new PhoneNumberIdentifier("112345556789"), "4:112345556789"); assertRawId(new PhoneNumberIdentifier("+112345556789").setRawId("4:otherFormat"), "4:otherFormat"); @@ -134,11 +331,20 @@ public void createIdentifierFromRawId() assertIdentifier("8:dod-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130", new CommunicationUserIdentifier("8:dod-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130")); assertIdentifier("8:gcch-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130", new CommunicationUserIdentifier("8:gcch-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130")); assertIdentifier("8:acs:something", new CommunicationUserIdentifier("8:acs:something")); + assertIdentifier("8:orgid:45ab2481-1c1c-4005-be24-0ffb879b1130", new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", false).setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); assertIdentifier("8:dod:45ab2481-1c1c-4005-be24-0ffb879b1130", new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", false).setCloudEnvironment(CommunicationCloudEnvironment.DOD)); assertIdentifier("8:gcch:45ab2481-1c1c-4005-be24-0ffb879b1130", new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", false).setCloudEnvironment(CommunicationCloudEnvironment.GCCH)); assertIdentifier("8:teamsvisitor:45ab2481-1c1c-4005-be24-0ffb879b1130", new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", true).setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); assertIdentifier("8:orgid:legacyFormat", new MicrosoftTeamsUserIdentifier("legacyFormat", false).setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); + + assertIdentifier("8:acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130", + new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC)); + assertIdentifier("8:dod-acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130", + new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.DOD)); + assertIdentifier("8:gcch-acs:3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37_7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d_45ab2481-1c1c-4005-be24-0ffb879b1130", + new TeamsExtensionUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130", "7f43a902-8c6f-4b77-91e1-67d3f3f4bb1d", "3e74a9c2-5d0b-4f88-936c-7ea2b21d4b37").setCloudEnvironment(CommunicationCloudEnvironment.GCCH)); + assertIdentifier("4:112345556789", new PhoneNumberIdentifier("112345556789")); assertIdentifier("4:+112345556789", new PhoneNumberIdentifier("+112345556789")); assertIdentifier("4:otherFormat", new PhoneNumberIdentifier("otherFormat")); @@ -152,7 +358,7 @@ public void createIdentifierFromRawId() assertIdentifier("28:gcch:45ab2481-1c1c-4005-be24-0ffb879b1130", new MicrosoftTeamsAppIdentifier(microsoftTeamsAppId, CommunicationCloudEnvironment.GCCH)); final IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, () -> CommunicationIdentifier.fromRawId(null)); - assertEquals("The parameter [rawId] cannot be null to empty.", illegalArgumentException.getMessage()); + assertEquals("The parameter [rawId] cannot be null or empty.", illegalArgumentException.getMessage()); } @Test @@ -186,6 +392,9 @@ public void rawIdStaysTheSameAfterConversionToIdentifierAndBack() assertRoundTrip("8:orgid:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRoundTrip("8:dod:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRoundTrip("8:gcch:45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRoundTrip("8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130_45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRoundTrip("8:dod-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130_45ab2481-1c1c-4005-be24-0ffb879b1130"); + assertRoundTrip("8:gcch-acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130_45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRoundTrip("8:teamsvisitor:45ab2481-1c1c-4005-be24-0ffb879b1130"); assertRoundTrip("8:orgid:legacyFormat"); assertRoundTrip("4:+112345556789");