diff --git a/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberAsyncClient.java b/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberAsyncClient.java index 61ac69041c37d..979507befa82e 100644 --- a/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberAsyncClient.java +++ b/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberAsyncClient.java @@ -25,6 +25,7 @@ import com.azure.communication.administration.models.UpdateNumberCapabilitiesResponse; import com.azure.communication.administration.models.NumberConfiguration; import com.azure.communication.administration.models.PhoneNumberSearch; +import com.azure.communication.administration.models.SearchStatus; import com.azure.communication.administration.models.UpdateNumberCapabilitiesRequest; import com.azure.communication.administration.models.UpdatePhoneNumberCapabilitiesResponse; import com.azure.communication.common.PhoneNumber; @@ -36,12 +37,19 @@ import com.azure.core.util.Context; import com.azure.core.util.FluxUtil; import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.polling.LongRunningOperationStatus; +import com.azure.core.util.polling.PollResponse; +import com.azure.core.util.polling.PollerFlux; +import com.azure.core.util.polling.PollingContext; import reactor.core.publisher.Mono; +import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.stream.Collectors; import static com.azure.core.util.FluxUtil.monoError; @@ -53,7 +61,6 @@ @ServiceClient(builder = PhoneNumberClientBuilder.class, isAsync = true) public final class PhoneNumberAsyncClient { private final ClientLogger logger = new ClientLogger(PhoneNumberAsyncClient.class); - private final PhoneNumberAdministrationsImpl phoneNumberAdministrations; PhoneNumberAsyncClient(PhoneNumberAdminClientImpl phoneNumberAdminClient) { @@ -757,4 +764,74 @@ Mono> purchaseSearchWithResponse(String searchId, Context context return monoError(logger, ex); } } + + /** + * Initiates a search and returns a {@link PhoneNumberSearch} usable by other functions + * This function returns a Long Running Operation poller that allows you to + * wait indefinitely until the operation is complete. + * + * @param options A {@link CreateSearchOptions} with the search options + * @param pollInterval The time our long running operation will keep on polling + * until it gets a result from the server + * @return A {@link PollerFlux} object with the search result + */ + @ServiceMethod(returns = ReturnType.COLLECTION) + public PollerFlux beginCreateSearch( + CreateSearchOptions options, Duration pollInterval) { + Objects.requireNonNull(options, "'options' cannot be null."); + Objects.requireNonNull(pollInterval, "'pollInterval' cannot be null."); + return new PollerFlux(pollInterval, + createSearchActivationOperation(options), + createSearchPollOperation(), + cancelSearchOperation(), + createSearchFetchResultOperation()); + } + + private Function, Mono> + createSearchActivationOperation(CreateSearchOptions options) { + return (pollingContext) -> { + Mono response = createSearch(options).flatMap(createSearchResponse -> { + String searchId = createSearchResponse.getSearchId(); + Mono phoneNumberSearch = getSearchById(searchId); + return phoneNumberSearch; + }); + return response; + }; + } + + private Function, Mono>> + createSearchPollOperation() { + return pollingContext -> + getSearchById(pollingContext.getLatestResponse().getValue().getSearchId()) + .flatMap(getSearchResponse -> { + SearchStatus status = getSearchResponse.getStatus(); + if (status.equals(SearchStatus.EXPIRED) + || status.equals(SearchStatus.CANCELLED) + || status.equals(SearchStatus.RESERVED)) { + return Mono.just(new PollResponse<>( + LongRunningOperationStatus.SUCCESSFULLY_COMPLETED, getSearchResponse)); + } + if (status.equals(SearchStatus.ERROR)) { + return Mono.just(new PollResponse<>( + LongRunningOperationStatus.FAILED, getSearchResponse)); + } + return Mono.just(new PollResponse<>(LongRunningOperationStatus.IN_PROGRESS, getSearchResponse)); + }); + } + + private BiFunction, + PollResponse, Mono> + cancelSearchOperation() { + return (pollingContext, firstResponse) -> { + cancelSearch(pollingContext.getLatestResponse().getValue().getSearchId()); + return Mono.just(pollingContext.getLatestResponse().getValue()); + }; + } + + private Function, + Mono> createSearchFetchResultOperation() { + return pollingContext -> { + return Mono.just(pollingContext.getLatestResponse().getValue()); + }; + } } diff --git a/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberClient.java b/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberClient.java index f06a4dcbb5f68..823de72653424 100644 --- a/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberClient.java +++ b/sdk/communication/azure-communication-administration/src/main/java/com/azure/communication/administration/PhoneNumberClient.java @@ -27,6 +27,9 @@ import com.azure.core.http.rest.PagedIterable; import com.azure.core.http.rest.Response; import com.azure.core.util.Context; +import com.azure.core.util.polling.SyncPoller; + +import java.time.Duration; import java.util.List; import java.util.Map; @@ -521,4 +524,19 @@ public void purchaseSearch(String searchId) { public Response purchaseSearchWithResponse(String searchId, Context context) { return phoneNumberAsyncClient.purchaseSearchWithResponse(searchId, context).block(); } + + /** + * Initiates a search and returns a {@link PhoneNumberSearch} usable by other functions + * This function returns a Long Running Operation poller. + * + * @param options A {@link CreateSearchOptions} with the search options + * @param pollInterval The time our long running operation will keep on polling + * until it gets a result from the server + * @return A {@link SyncPoller} object with the search result + */ + @ServiceMethod(returns = ReturnType.COLLECTION) + public SyncPoller beginCreateSearch( + CreateSearchOptions options, Duration pollInterval) { + return phoneNumberAsyncClient.beginCreateSearch(options, pollInterval).getSyncPoller(); + } } diff --git a/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberAsyncClientIntegrationTest.java b/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberAsyncClientIntegrationTest.java index 87b2771772c9d..6e8edd8251f24 100644 --- a/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberAsyncClientIntegrationTest.java +++ b/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberAsyncClientIntegrationTest.java @@ -23,12 +23,16 @@ import com.azure.communication.common.PhoneNumber; import com.azure.core.http.rest.PagedFlux; import com.azure.core.http.rest.Response; +import com.azure.core.util.polling.PollerFlux; +import com.azure.core.util.polling.AsyncPollResponse; +import com.azure.core.util.polling.LongRunningOperationStatus; import com.azure.core.util.Context; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -463,6 +467,31 @@ public void releasePhoneNumbersWithResponse() { .verifyComplete(); } + @Test() + public void beginCreateSearch() { + List phonePlanIds = new ArrayList<>(); + phonePlanIds.add(PHONE_PLAN_ID); + + CreateSearchOptions createSearchOptions = new CreateSearchOptions(); + createSearchOptions + .setAreaCode(AREA_CODE_FOR_SEARCH) + .setDescription(SEARCH_OPTIONS_DESCRIPTION) + .setDisplayName(SEARCH_OPTIONS_NAME) + .setPhonePlanIds(phonePlanIds) + .setQuantity(2); + + Duration duration = Duration.ofSeconds(1); + PhoneNumberAsyncClient client = this.getClient(); + PollerFlux poller = + client.beginCreateSearch(createSearchOptions, duration); + AsyncPollResponse asyncRes = + poller.takeUntil(apr -> apr.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) + .blockLast(); + PhoneNumberSearch testResult = asyncRes.getValue(); + assertEquals(testResult.getPhoneNumbers().size(), 2); + assertNotNull(testResult.getSearchId()); + } + private PhoneNumberAsyncClient getClient() { return super.getClientBuilder().buildAsyncClient(); } diff --git a/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberIntegrationTestBase.java b/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberIntegrationTestBase.java index f2e7aadcf8583..6ba88408896c9 100644 --- a/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberIntegrationTestBase.java +++ b/sdk/communication/azure-communication-administration/src/test/java/com/azure/communication/administration/PhoneNumberIntegrationTestBase.java @@ -60,6 +60,10 @@ public class PhoneNumberIntegrationTestBase extends TestBase { Configuration.getGlobalConfiguration().get("LOCATION_OPTION_STATE", "CA"); protected static final String LOCATION_OPTION_CITY = Configuration.getGlobalConfiguration().get("LOCATION_OPTION_CITY", "NOAM-US-CA-LA"); + protected static final String SEARCH_OPTIONS_DESCRIPTION = + Configuration.getGlobalConfiguration().get("SEARCH_OPTIONS_DESCRIPTION", "testsearch20200014"); + protected static final String SEARCH_OPTIONS_NAME = + Configuration.getGlobalConfiguration().get("SEARCH_OPTIONS_NAME", "testsearch20200014"); protected PhoneNumberClientBuilder getClientBuilder() { HttpClient httpClient; diff --git a/sdk/communication/azure-communication-administration/src/test/resources/session-records/beginCreateSearch.json b/sdk/communication/azure-communication-administration/src/test/resources/session-records/beginCreateSearch.json new file mode 100644 index 0000000000000..6ec687b238d06 --- /dev/null +++ b/sdk/communication/azure-communication-administration/src/test/resources/session-records/beginCreateSearch.json @@ -0,0 +1,59 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://REDACTED.communication.azure.com/administration/phonenumbers/searches?api-version=2020-07-20-preview1", + "Headers" : { + "User-Agent" : "azsdk-java-azure-communication-administration/1.0.0-beta.1 (11.0.8; Windows 10; 10.0)", + "Content-Type" : "application/json" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "X-Processing-Time" : "2106ms", + "MS-CV" : "AudA+TBsSkC2dy5EORj0jg.0", + "retry-after" : "0", + "X-Azure-Ref" : "0/598XwAAAABNqI5PZ5BrTocglFXesDJDREVOMDJFREdFMDMxNQA5ZmM3YjUxOS1hOGNjLTRmODktOTM1ZS1jOTE0OGFlMDllODE=", + "StatusCode" : "201", + "Body" : "{\"searchId\":\"44b70e2f-6521-454e-a8ea-67ab95927a13\"}", + "Date" : "Tue, 06 Oct 2020 16:49:05 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.communication.azure.com/administration/phonenumbers/searches/44b70e2f-6521-454e-a8ea-67ab95927a13?api-version=2020-07-20-preview1", + "Headers" : { + "User-Agent" : "azsdk-java-azure-communication-administration/1.0.0-beta.1 (11.0.8; Windows 10; 10.0)" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "X-Processing-Time" : "351ms", + "MS-CV" : "UsgvNonyy0W78Wb+YlAR/Q.0", + "retry-after" : "0", + "X-Azure-Ref" : "0B6B8XwAAAABJLU8C50vpQr8eJDv7BnURREVOMDJFREdFMDMxNQA5ZmM3YjUxOS1hOGNjLTRmODktOTM1ZS1jOTE0OGFlMDllODE=", + "StatusCode" : "200", + "Body" : "{\"searchId\":\"44b70e2f-6521-454e-a8ea-67ab95927a13\",\"displayName\":\"testsearch20200014\",\"createdAt\":\"2020-10-06T16:49:05.1044519+00:00\",\"description\":\"testsearch20200014\",\"phonePlanIds\":[\"27b53eec-8ff4-4070-8900-fbeaabfd158a\"],\"areaCode\":\"323\",\"quantity\":2,\"locationOptions\":[],\"status\":\"Pending\",\"phoneNumbers\":[]}", + "Date" : "Tue, 06 Oct 2020 16:49:11 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.communication.azure.com/administration/phonenumbers/searches/44b70e2f-6521-454e-a8ea-67ab95927a13?api-version=2020-07-20-preview1", + "Headers" : { + "User-Agent" : "azsdk-java-azure-communication-administration/1.0.0-beta.1 (11.0.8; Windows 10; 10.0)" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "X-Processing-Time" : "292ms", + "MS-CV" : "rgPQQ3XR50SFtXr68Qefqw.0", + "retry-after" : "0", + "X-Azure-Ref" : "0DaB8XwAAAADdZnkaYhXqS76qjA9LTed8REVOMDJFREdFMDMxNQA5ZmM3YjUxOS1hOGNjLTRmODktOTM1ZS1jOTE0OGFlMDllODE=", + "StatusCode" : "200", + "Body" : "{\"searchId\":\"44b70e2f-6521-454e-a8ea-67ab95927a13\",\"displayName\":\"testsearch20200014\",\"createdAt\":\"2020-10-06T16:49:05.1044519+00:00\",\"description\":\"testsearch20200014\",\"phonePlanIds\":[\"27b53eec-8ff4-4070-8900-fbeaabfd158a\"],\"areaCode\":\"323\",\"quantity\":2,\"locationOptions\":[],\"status\":\"Reserved\",\"phoneNumbers\":[\"+13234866789\",\"+13234866792\"],\"reservationExpiryDate\":\"2020-10-06T17:05:13.5997531+00:00\"}", + "Date" : "Tue, 06 Oct 2020 16:49:16 GMT", + "Content-Type" : "application/json; charset=utf-8" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file