customPolicies = new ArrayList<>();
+ private ClientOptions clientOptions;
+ private RetryPolicy retryPolicy;
+ private RetryOptions retryOptions;
+
+ /**
+ * Public default constructor
+ */
+ public CallAutomationClientBuilder() {
+
+ }
+
+ /**
+ * Set endpoint of the service.
+ *
+ * @param endpoint url of the service.
+ * @return CallAutomationClientBuilder object.
+ */
+ @Override
+ public CallAutomationClientBuilder endpoint(String endpoint) {
+ this.endpoint = Objects.requireNonNull(endpoint, "'endpoint' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link HttpPipeline} to use for the service client.
+ *
+ * Note: It is important to understand the precedence order of the HttpTrait APIs. In
+ * particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
+ * they will be ignored. If no {@link HttpPipeline} is specified, a HTTP pipeline will be constructed internally
+ * based on the settings provided to this trait. Additionally, there may be other APIs in types that implement this
+ * trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
+ * documentation of types that implement this trait to understand the full set of implications.
+ *
+ * @param pipeline {@link HttpPipeline} to use for sending service requests and receiving responses,
+ * if a pipeline is not supplied, the
+ * credential and httpClient fields must be set.
+ * @return CallAutomationClientBuilder object.
+ */
+ @Override
+ public CallAutomationClientBuilder pipeline(HttpPipeline pipeline) {
+ this.pipeline = Objects.requireNonNull(pipeline, "'pipeline' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link TokenCredential} used to authorize requests sent to the service. Refer to the Azure SDK for Java
+ * identity and authentication
+ * documentation for more details on proper usage of the {@link TokenCredential} type.
+ *
+ * @param tokenCredential {@link TokenCredential} used to authorize requests sent to the service.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ * @throws NullPointerException If {@code tokenCredential} is null.
+ */
+ @Override
+ public CallAutomationClientBuilder credential(TokenCredential tokenCredential) {
+ this.tokenCredential = Objects.requireNonNull(tokenCredential, "'tokenCredential' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link AzureKeyCredential} used to authenticate HTTP requests.
+ *
+ * @param keyCredential The {@link AzureKeyCredential} used to authenticate HTTP
+ * requests.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ * @throws NullPointerException If {@code keyCredential} is null.
+ */
+ @Override
+ public CallAutomationClientBuilder credential(AzureKeyCredential keyCredential) {
+ this.azureKeyCredential = Objects.requireNonNull(keyCredential, "'keyCredential' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Set connectionString to use.
+ *
+ * @param connectionString connection string to set.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ @Override
+ public CallAutomationClientBuilder connectionString(String connectionString) {
+ Objects.requireNonNull(connectionString, "'connectionString' cannot be null.");
+ this.connectionString = connectionString;
+ return this;
+ }
+
+ /**
+ * Sets the retry policy to use (using the RetryPolicy type).
+ *
+ * Setting this is mutually exclusive with using {@link #retryOptions(RetryOptions)}.
+ *
+ * @param retryPolicy object to be applied
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ public CallAutomationClientBuilder retryPolicy(RetryPolicy retryPolicy) {
+ this.retryPolicy = Objects.requireNonNull(retryPolicy, "'retryPolicy' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link RetryOptions} for all the requests made through the client.
+ *
+ *
Note: It is important to understand the precedence order of the HttpTrait APIs. In
+ * particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
+ * they will be ignored. If no {@link HttpPipeline} is specified, a HTTP pipeline will be constructed internally
+ * based on the settings provided to this trait. Additionally, there may be other APIs in types that implement this
+ * trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
+ * documentation of types that implement this trait to understand the full set of implications.
+ *
+ * Setting this is mutually exclusive with using {@link #retryPolicy(RetryPolicy)}.
+ *
+ * @param retryOptions The {@link RetryOptions} to use for all the requests made through the client.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ @Override
+ public CallAutomationClientBuilder retryOptions(RetryOptions retryOptions) {
+ this.retryOptions = retryOptions;
+ return this;
+ }
+
+ /**
+ * Sets the configuration object used to retrieve environment configuration
+ * values during building of the client.
+ *
+ * @param configuration Configuration store used to retrieve environment
+ * configurations.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ @Override
+ public CallAutomationClientBuilder configuration(Configuration configuration) {
+ this.configuration = Objects.requireNonNull(configuration, "'configuration' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link HttpLogOptions logging configuration} to use when sending and receiving requests to and from
+ * the service. If a {@code logLevel} is not provided, default value of {@link HttpLogDetailLevel#NONE} is set.
+ *
+ *
Note: It is important to understand the precedence order of the HttpTrait APIs. In
+ * particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
+ * they will be ignored. If no {@link HttpPipeline} is specified, a HTTP pipeline will be constructed internally
+ * based on the settings provided to this trait. Additionally, there may be other APIs in types that implement this
+ * trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
+ * documentation of types that implement this trait to understand the full set of implications.
+ *
+ * @param logOptions The {@link HttpLogOptions logging configuration} to use when sending and receiving requests to
+ * and from the service.
+ * @return The updated {@link CallAutomationClientBuilder} object.
+ */
+ @Override
+ public CallAutomationClientBuilder httpLogOptions(HttpLogOptions logOptions) {
+ this.httpLogOptions = Objects.requireNonNull(logOptions, "'logOptions' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Sets the {@link CallingServerServiceVersion} that is used when making API requests.
+ *
+ * If a service version is not provided, the service version that will be used will be the latest known service
+ * version based on the version of the client library being used. If no service version is specified, updating to a
+ * newer version of the client library will have the result of potentially moving to a newer service version.
+ *
+ * Targeting a specific service version may also mean that the service will return an error for newer APIs.
+ *
+ * @param version {@link CallingServerServiceVersion} of the service to be used when making requests.
+ * @return Updated CallAutomationClientBuilder object
+ */
+ public CallAutomationClientBuilder serviceVersion(CallingServerServiceVersion version) {
+ return this;
+ }
+
+ /**
+ * Sets the {@link HttpClient} to use for sending and receiving requests to and from the service.
+ *
+ *
Note: It is important to understand the precedence order of the HttpTrait APIs. In
+ * particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
+ * they will be ignored. If no {@link HttpPipeline} is specified, a HTTP pipeline will be constructed internally
+ * based on the settings provided to this trait. Additionally, there may be other APIs in types that implement this
+ * trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
+ * documentation of types that implement this trait to understand the full set of implications.
+ *
+ * @param httpClient The {@link HttpClient} to use for requests.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ @Override
+ public CallAutomationClientBuilder httpClient(HttpClient httpClient) {
+ this.httpClient = Objects.requireNonNull(httpClient, "'httpClient' cannot be null.");
+ return this;
+ }
+
+ /**
+ * Adds a {@link HttpPipelinePolicy pipeline policy} to apply on each request sent.
+ *
+ * Note: It is important to understand the precedence order of the HttpTrait APIs. In
+ * particular, if a {@link HttpPipeline} is specified, this takes precedence over all other APIs in the trait, and
+ * they will be ignored. If no {@link HttpPipeline} is specified, a HTTP pipeline will be constructed internally
+ * based on the settings provided to this trait. Additionally, there may be other APIs in types that implement this
+ * trait that are also ignored if an {@link HttpPipeline} is specified, so please be sure to refer to the
+ * documentation of types that implement this trait to understand the full set of implications.
+ *
+ * @param customPolicy A {@link HttpPipelinePolicy pipeline policy}.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ * @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
+ */
+ @Override
+ public CallAutomationClientBuilder addPolicy(HttpPipelinePolicy customPolicy) {
+ this.customPolicies.add(Objects.requireNonNull(customPolicy, "'customPolicy' cannot be null."));
+ return this;
+ }
+
+ /**
+ * Create asynchronous client applying HMACAuthenticationPolicy,
+ * UserAgentPolicy, RetryPolicy, and CookiePolicy. Additional HttpPolicies
+ * specified by additionalPolicies will be applied after them
+ *
+ * @return The updated {@link CallAutomationClientBuilder} object.
+ * @throws IllegalStateException If both {@link #retryOptions(RetryOptions)}
+ * and {@link #retryPolicy(RetryPolicy)} have been set.
+ */
+ public CallAutomationAsyncClient buildAsyncClient() {
+ return new CallAutomationAsyncClient(createServiceImpl());
+ }
+
+ /**
+ * Create synchronous client applying HmacAuthenticationPolicy, UserAgentPolicy,
+ * RetryPolicy, and CookiePolicy. Additional HttpPolicies specified by
+ * additionalPolicies will be applied after them.
+ *
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ * @throws IllegalStateException If both {@link #retryOptions(RetryOptions)}
+ * and {@link #retryPolicy(RetryPolicy)} have been set.
+ */
+ public CallAutomationClient buildClient() {
+ return new CallAutomationClient(buildAsyncClient());
+ }
+
+ private AzureCommunicationCallAutomationServiceImpl createServiceImpl() {
+ boolean isConnectionStringSet = connectionString != null && !connectionString.trim().isEmpty();
+ boolean isEndpointSet = endpoint != null && !endpoint.trim().isEmpty();
+ boolean isAzureKeyCredentialSet = azureKeyCredential != null;
+ boolean isTokenCredentialSet = tokenCredential != null;
+ boolean isCustomEndpointUsed;
+
+ String customEndpointEnabled = Configuration.getGlobalConfiguration().get("COMMUNICATION_CUSTOM_ENDPOINT_ENABLED",
+ "false");
+ isCustomEndpointUsed = Objects.equals(customEndpointEnabled, "true");
+
+ if (isConnectionStringSet && isEndpointSet && !isCustomEndpointUsed) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Both 'connectionString' and 'endpoint' are set. Just one may be used."));
+ }
+
+ if (((!isConnectionStringSet && !isTokenCredentialSet) || !isEndpointSet) && isCustomEndpointUsed) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Custom Endpoint mode requires 'ConnectionString/TokenCredential' and 'Endpoint' both to be set. Requirement is not fulfilled, changing back to normal mode."));
+ }
+
+ if (isConnectionStringSet && isAzureKeyCredentialSet) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Both 'connectionString' and 'keyCredential' are set. Just one may be used."));
+ }
+
+ if (isConnectionStringSet && isTokenCredentialSet) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Both 'connectionString' and 'tokenCredential' are set. Just one may be used."));
+ }
+
+ if (isAzureKeyCredentialSet && isTokenCredentialSet) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Both 'tokenCredential' and 'keyCredential' are set. Just one may be used."));
+ }
+
+ if (isCustomEndpointUsed && !isTokenCredentialSet) {
+ CommunicationConnectionString connectionStringObject = new CommunicationConnectionString(connectionString);
+ String accessKey = connectionStringObject.getAccessKey();
+ credential(new AzureKeyCredential(accessKey));
+ } else if (isConnectionStringSet) {
+ CommunicationConnectionString connectionStringObject = new CommunicationConnectionString(connectionString);
+ String endpoint = connectionStringObject.getEndpoint();
+ String accessKey = connectionStringObject.getAccessKey();
+ endpoint(endpoint).credential(new AzureKeyCredential(accessKey));
+ }
+
+ Objects.requireNonNull(endpoint);
+ if (isTokenCredentialSet) {
+ try {
+ hostName = getHostNameFromEndpoint();
+ } catch (MalformedURLException e) {
+ throw logger.logExceptionAsError(new RuntimeException(e.getMessage()));
+ }
+ }
+
+ HttpPipeline builderPipeline = pipeline;
+ if (pipeline == null) {
+ builderPipeline = createHttpPipeline(httpClient, isCustomEndpointUsed);
+ }
+
+ AzureCommunicationCallAutomationServiceImplBuilder clientBuilder = new AzureCommunicationCallAutomationServiceImplBuilder();
+ clientBuilder.endpoint(endpoint).pipeline(builderPipeline);
+
+ return clientBuilder.buildClient();
+ }
+
+ /**
+ * Allows the user to set a variety of client-related options, such as
+ * user-agent string, headers, etc.
+ *
+ * @param clientOptions object to be applied.
+ * @return Updated {@link CallAutomationClientBuilder} object.
+ */
+ public CallAutomationClientBuilder clientOptions(ClientOptions clientOptions) {
+ this.clientOptions = clientOptions;
+ return this;
+ }
+
+ private List createHttpPipelineAuthPolicies(boolean isCustomEndpointUsed) throws MalformedURLException {
+ if (tokenCredential != null && azureKeyCredential != null) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(
+ "Both 'credential' and 'keyCredential' are set. Just one may be used."));
+ }
+
+ List pipelinePolicies = new ArrayList<>();
+ if (tokenCredential != null) {
+ pipelinePolicies.add(new BearerTokenAuthenticationPolicy(tokenCredential,
+ "https://communication.azure.com//.default"));
+ Map httpHeaders = new HashMap<>();
+ httpHeaders.put("x-ms-host", hostName);
+ pipelinePolicies.add(new AddHeadersPolicy(new HttpHeaders(httpHeaders)));
+ } else if (azureKeyCredential != null) {
+ if (isCustomEndpointUsed) {
+ String acsEndpoint = (new CommunicationConnectionString(connectionString)).getEndpoint();
+ pipelinePolicies.add(new CustomHmacAuthenticationPolicy(azureKeyCredential, (new URL(acsEndpoint)).getHost()));
+ } else {
+ pipelinePolicies.add(new HmacAuthenticationPolicy(azureKeyCredential));
+ }
+ } else {
+ throw logger.logExceptionAsError(
+ new IllegalArgumentException("Missing credential information while building a client."));
+ }
+
+ return pipelinePolicies;
+ }
+
+ private HttpPipeline createHttpPipeline(HttpClient httpClient, boolean isCustomEndpointUsed) {
+ if (pipeline != null) {
+ return pipeline;
+ }
+
+ List policyList = new ArrayList<>();
+
+ ClientOptions buildClientOptions = (clientOptions == null) ? new ClientOptions() : clientOptions;
+ HttpLogOptions buildLogOptions = (httpLogOptions == null) ? new HttpLogOptions() : httpLogOptions;
+
+ String applicationId = null;
+ if (!CoreUtils.isNullOrEmpty(buildClientOptions.getApplicationId())) {
+ applicationId = buildClientOptions.getApplicationId();
+ } else if (!CoreUtils.isNullOrEmpty(buildLogOptions.getApplicationId())) {
+ applicationId = buildLogOptions.getApplicationId();
+ }
+
+ // Add required policies
+ String clientName = properties.getOrDefault(SDK_NAME, "UnknownName");
+ String clientVersion = properties.getOrDefault(SDK_VERSION, "UnknownVersion");
+ policyList.add(new UserAgentPolicy(applicationId, clientName, clientVersion, configuration));
+ policyList.add(new RequestIdPolicy());
+ policyList.add(ClientBuilderUtil.validateAndGetRetryPolicy(retryPolicy, retryOptions));
+ policyList.add(new RedirectPolicy());
+ try {
+ policyList.addAll(createHttpPipelineAuthPolicies(isCustomEndpointUsed));
+ } catch (Exception e) {
+ throw logger.logExceptionAsError(
+ new IllegalArgumentException("Invalid ACS Endpoint exception: " + e));
+ }
+
+ policyList.add(new CookiePolicy());
+
+ // Add additional policies
+ if (!customPolicies.isEmpty()) {
+ policyList.addAll(customPolicies);
+ }
+
+ // Add logging policy
+ policyList.add(new HttpLoggingPolicy(getHttpLogOptions()));
+
+ return new HttpPipelineBuilder().policies(policyList.toArray(new HttpPipelinePolicy[0])).httpClient(httpClient)
+ .build();
+ }
+
+ private HttpLogOptions getHttpLogOptions() {
+ if (httpLogOptions == null) {
+ httpLogOptions = new HttpLogOptions();
+ }
+
+ return httpLogOptions;
+ }
+
+ private String getHostNameFromEndpoint() throws MalformedURLException {
+ return new URL(endpoint).getHost();
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnection.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnection.java
new file mode 100644
index 0000000000000..aa4c92cb37b44
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnection.java
@@ -0,0 +1,236 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.models.CallParticipant;
+import com.azure.communication.callautomation.models.AddParticipantsOptions;
+import com.azure.communication.callautomation.models.AddParticipantsResult;
+import com.azure.communication.callautomation.models.CallConnectionProperties;
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.ListParticipantsResult;
+import com.azure.communication.callautomation.models.RemoveParticipantsResult;
+import com.azure.communication.callautomation.models.TransferCallResult;
+import com.azure.communication.callautomation.models.TransferToParticipantCallOptions;
+import com.azure.communication.common.CommunicationIdentifier;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.http.rest.Response;
+import com.azure.core.util.Context;
+
+import java.util.List;
+
+/**
+ * CallConnection for mid-call actions
+ */
+public class CallConnection {
+ private final CallConnectionAsync callConnectionAsync;
+
+ CallConnection(CallConnectionAsync callConnectionAsync) {
+ this.callConnectionAsync = callConnectionAsync;
+ }
+
+ /**
+ * Get call connection properties.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public CallConnectionProperties getCallProperties() {
+ return callConnectionAsync.getCallProperties().block();
+ }
+
+ /**
+ * Get call connection properties.
+ *
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getCallPropertiesWithResponse(Context context) {
+ return callConnectionAsync.getCallPropertiesWithResponseInternal(context).block();
+ }
+
+ /**
+ * Hangup a call.
+ *
+ * @param isForEveryone determine if the call is handed up for all participants.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful hangup request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Void hangUp(boolean isForEveryone) {
+ return callConnectionAsync.hangUp(isForEveryone).block();
+ }
+
+ /**
+ * Hangup a call.
+ *
+ * @param isForEveryone determine if the call is handed up for all participants.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful hangup request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response hangUpWithResponse(boolean isForEveryone, Context context) {
+ return callConnectionAsync.hangUpWithResponseInternal(isForEveryone, context).block();
+ }
+
+ /**
+ * Get a specific participant.
+ *
+ * @param participantMri The participant.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public CallParticipant getParticipant(String participantMri) {
+ return callConnectionAsync.getParticipant(participantMri).block();
+ }
+
+ /**
+ * Get all participants.
+ *
+ * @param participantMri The participant.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getParticipantWithResponse(String participantMri, Context context) {
+ return callConnectionAsync.getParticipantWithResponseInternal(participantMri, context).block();
+ }
+
+ /**
+ * Get all participants.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public ListParticipantsResult listParticipants() {
+ return callConnectionAsync.listParticipants().block();
+ }
+
+ /**
+ * Get all participants.
+ *
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response listParticipantsWithResponse(Context context) {
+ return callConnectionAsync.listParticipantsWithResponseInternal(context).block();
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param transferToParticipantCallOptions Options bag for transferToParticipantCall
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful call termination request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public TransferCallResult transferToParticipantCall(TransferToParticipantCallOptions transferToParticipantCallOptions) {
+ return callConnectionAsync.transferToParticipantCall(transferToParticipantCallOptions).block();
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param transferToParticipantCallOptions Options bag for transferToParticipantCall
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful call termination request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response transferToParticipantCallWithResponse(
+ TransferToParticipantCallOptions transferToParticipantCallOptions, Context context) {
+ return callConnectionAsync.transferToParticipantCallWithResponseInternal(transferToParticipantCallOptions, context).block();
+ }
+
+ /**
+ * Add a participant to the call.
+ *
+ * @param addParticipantsOptions Options bag for addParticipants
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public AddParticipantsResult addParticipants(AddParticipantsOptions addParticipantsOptions) {
+ return callConnectionAsync.addParticipants(addParticipantsOptions).block();
+ }
+
+ /**
+ * Add a participant to the call.
+ *
+ * @param addParticipantsOptions Options bag for addParticipants
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response addParticipantsWithResponse(AddParticipantsOptions addParticipantsOptions,
+ Context context) {
+ return callConnectionAsync.addParticipantsWithResponseInternal(addParticipantsOptions, context).block();
+ }
+
+ /**
+ * Remove a list of participants from the call.
+ *
+ * @param participantsToRemove The identifier list of the participant to be removed.
+ * @param operationContext The operation context. Optional
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public RemoveParticipantsResult removeParticipants(List participantsToRemove,
+ String operationContext) {
+ return callConnectionAsync.removeParticipants(participantsToRemove, operationContext).block();
+ }
+
+ /**
+ * Remove a list of participant from the call.
+ *
+ * @param participantsToRemove The identifier list of the participant to be removed.
+ * @param operationContext The operation context. Optional
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response removeParticipantsWithResponse(List participantsToRemove,
+ String operationContext, Context context) {
+ return callConnectionAsync.removeParticipantsWithResponseInternal(participantsToRemove, operationContext, context).block();
+ }
+
+ //region Content management Actions
+ /***
+ * Returns an object of CallContent
+ *
+ * @return a CallContentAsync.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public CallMedia getCallMedia() {
+ return new CallMedia(callConnectionAsync.getCallMediaAsync());
+ }
+
+ //endregion
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnectionAsync.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnectionAsync.java
new file mode 100644
index 0000000000000..25c1cf961f672
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallConnectionAsync.java
@@ -0,0 +1,382 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.implementation.CallConnectionsImpl;
+import com.azure.communication.callautomation.implementation.ContentsImpl;
+import com.azure.communication.callautomation.implementation.accesshelpers.AddParticipantsResponseConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.CallConnectionPropertiesConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.ErrorConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.ListParticipantsResponseConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.RemoveParticipantsResponseConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.TransferCallResponseConstructorProxy;
+import com.azure.communication.callautomation.implementation.converters.CallParticipantConverter;
+import com.azure.communication.callautomation.implementation.converters.CommunicationIdentifierConverter;
+import com.azure.communication.callautomation.implementation.converters.PhoneNumberIdentifierConverter;
+import com.azure.communication.callautomation.implementation.models.AddParticipantsRequestInternal;
+import com.azure.communication.callautomation.implementation.models.CommunicationIdentifierModel;
+import com.azure.communication.callautomation.implementation.models.RemoveParticipantsRequestInternal;
+import com.azure.communication.callautomation.implementation.models.TransferToParticipantRequestInternal;
+import com.azure.communication.callautomation.models.AddParticipantsResult;
+import com.azure.communication.callautomation.models.CallParticipant;
+import com.azure.communication.callautomation.models.AddParticipantsOptions;
+import com.azure.communication.callautomation.models.CallConnectionProperties;
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.ListParticipantsResult;
+import com.azure.communication.callautomation.models.RemoveParticipantsResult;
+import com.azure.communication.callautomation.models.TransferCallResult;
+import com.azure.communication.callautomation.models.TransferToParticipantCallOptions;
+import com.azure.communication.common.CommunicationIdentifier;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.SimpleResponse;
+import com.azure.core.util.Context;
+import com.azure.core.util.FluxUtil;
+import com.azure.core.util.logging.ClientLogger;
+import reactor.core.publisher.Mono;
+
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.azure.core.util.FluxUtil.monoError;
+import static com.azure.core.util.FluxUtil.withContext;
+
+/**
+ * CallConnectionAsync for mid-call actions
+ */
+public class CallConnectionAsync {
+ private final String callConnectionId;
+ private final CallConnectionsImpl callConnectionInternal;
+ private final ContentsImpl contentsInternal;
+ private final ClientLogger logger;
+
+ CallConnectionAsync(
+ String callConnectionId,
+ CallConnectionsImpl callConnectionInternal,
+ ContentsImpl contentsInternal) {
+ this.callConnectionId = callConnectionId;
+ this.callConnectionInternal = callConnectionInternal;
+ this.contentsInternal = contentsInternal;
+ this.logger = new ClientLogger(CallConnectionAsync.class);
+ }
+
+ /**
+ * Get call connection properties.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getCallProperties() {
+ return getCallPropertiesWithResponse().flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Get call connection properties.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getCallPropertiesWithResponse() {
+ return withContext(this::getCallPropertiesWithResponseInternal);
+ }
+
+ Mono> getCallPropertiesWithResponseInternal(Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ return callConnectionInternal.getCallWithResponseAsync(callConnectionId, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response -> {
+ try {
+ return new SimpleResponse<>(response, CallConnectionPropertiesConstructorProxy.create(response.getValue()));
+ } catch (URISyntaxException e) {
+ throw logger.logExceptionAsError(new RuntimeException(e));
+ }
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Hangup a call.
+ *
+ * @param isForEveryone determine if the call is handed up for all participants.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful hangup request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono hangUp(boolean isForEveryone) {
+ return hangUpWithResponse(isForEveryone).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Hangup a call.
+ *
+ * @param isForEveryone determine if the call is handed up for all participants.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful hangup request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> hangUpWithResponse(boolean isForEveryone) {
+ return withContext(context -> hangUpWithResponseInternal(isForEveryone, context));
+ }
+
+ Mono> hangUpWithResponseInternal(boolean isForEveryone, Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ return (isForEveryone ? callConnectionInternal.terminateCallWithResponseAsync(callConnectionId, context)
+ : callConnectionInternal.hangupCallWithResponseAsync(callConnectionId, context))
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Get a specific participant.
+ *
+ * @param participantMri MRI of the participants to retrieve.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getParticipant(String participantMri) {
+ return getParticipantWithResponse(participantMri).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Get a specific participant.
+ *
+ * @param participantMri MRI of the participants to retrieve.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getParticipantWithResponse(String participantMri) {
+ return withContext(context -> getParticipantWithResponseInternal(participantMri, context));
+ }
+
+ Mono> getParticipantWithResponseInternal(String participantMri, Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ return callConnectionInternal.getParticipantWithResponseAsync(callConnectionId, participantMri, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response ->
+ new SimpleResponse<>(response, CallParticipantConverter.convert(response.getValue())));
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Get all participants.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono listParticipants() {
+ return listParticipantsWithResponse().flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Get all participants.
+ *
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful get call connection request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> listParticipantsWithResponse() {
+ return withContext(this::listParticipantsWithResponseInternal);
+ }
+
+ Mono> listParticipantsWithResponseInternal(Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ return callConnectionInternal.getParticipantsWithResponseAsync(callConnectionId, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response -> new SimpleResponse<>(response,
+ ListParticipantsResponseConstructorProxy.create(response.getValue())));
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param transferToParticipantCallOptions Options bag for transferToParticipantCall
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response payload for a successful call termination request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono transferToParticipantCall(
+ TransferToParticipantCallOptions transferToParticipantCallOptions) {
+ return transferToParticipantCallWithResponse(transferToParticipantCallOptions).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param transferToParticipantCallOptions Options bag for transferToParticipantCall
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful call termination request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> transferToParticipantCallWithResponse(
+ TransferToParticipantCallOptions transferToParticipantCallOptions) {
+ return withContext(context -> transferToParticipantCallWithResponseInternal(transferToParticipantCallOptions, context));
+ }
+
+ Mono> transferToParticipantCallWithResponseInternal(
+ TransferToParticipantCallOptions transferToParticipantCallOptions, Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ TransferToParticipantRequestInternal request = new TransferToParticipantRequestInternal()
+ .setTargetParticipant(CommunicationIdentifierConverter.convert(transferToParticipantCallOptions.getTargetParticipant()))
+ .setTransfereeCallerId(PhoneNumberIdentifierConverter.convert(transferToParticipantCallOptions.getTransfereeCallerId()))
+ .setUserToUserInformation(transferToParticipantCallOptions.getUserToUserInformation())
+ .setOperationContext(transferToParticipantCallOptions.getOperationContext());
+
+ return callConnectionInternal.transferToParticipantWithResponseAsync(callConnectionId, request, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response ->
+ new SimpleResponse<>(response, TransferCallResponseConstructorProxy.create(response.getValue())));
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Add a participant to the call.
+ *
+ * @param addParticipantsOptions Options bag for addParticipants
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono addParticipants(AddParticipantsOptions addParticipantsOptions) {
+ return addParticipantsWithResponse(addParticipantsOptions).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Add a participant to the call.
+ *
+ * @param addParticipantsOptions Options bag for addParticipants
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> addParticipantsWithResponse(AddParticipantsOptions addParticipantsOptions) {
+ return withContext(context -> addParticipantsWithResponseInternal(addParticipantsOptions, context));
+ }
+
+ Mono> addParticipantsWithResponseInternal(AddParticipantsOptions addParticipantsOptions,
+ Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+ List participantModels = addParticipantsOptions.getParticipants()
+ .stream().map(CommunicationIdentifierConverter::convert).collect(Collectors.toList());
+
+ AddParticipantsRequestInternal request = new AddParticipantsRequestInternal()
+ .setParticipantsToAdd(participantModels)
+ .setSourceCallerId(PhoneNumberIdentifierConverter.convert(addParticipantsOptions.getSourceCallerId()))
+ .setOperationContext(addParticipantsOptions.getOperationContext());
+
+ // Need to do a null check since it is optional; it might be a null and breaks the get function as well as type casting.
+ if (addParticipantsOptions.getInvitationTimeout() != null) {
+ request.setInvitationTimeoutInSeconds((int) addParticipantsOptions.getInvitationTimeout().getSeconds());
+ }
+
+ return callConnectionInternal.addParticipantWithResponseAsync(callConnectionId, request, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response -> new SimpleResponse<>(response, AddParticipantsResponseConstructorProxy.create(response.getValue())));
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Remove a list of participants from the call.
+ *
+ * @param participantsToRemove The identifier list of the participant to be removed.
+ * @param operationContext The operation context. Optional
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono removeParticipants(List participantsToRemove,
+ String operationContext) {
+ return removeParticipantsWithResponse(participantsToRemove, operationContext).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Remove a list of participants from the call.
+ *
+ * @param participantsToRemove The identifier list of the participant to be removed.
+ * @param operationContext The operation context. Optional
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful add participant request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> removeParticipantsWithResponse(List participantsToRemove,
+ String operationContext) {
+ return withContext(context -> removeParticipantsWithResponseInternal(participantsToRemove, operationContext, context));
+ }
+
+ Mono> removeParticipantsWithResponseInternal(List participantsToRemove,
+ String operationContext, Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+ List participantModels = participantsToRemove
+ .stream().map(CommunicationIdentifierConverter::convert).collect(Collectors.toList());
+
+ RemoveParticipantsRequestInternal request = new RemoveParticipantsRequestInternal()
+ .setParticipantsToRemove(participantModels)
+ .setOperationContext(operationContext);
+
+ return callConnectionInternal.removeParticipantsWithResponseAsync(callConnectionId, request, context)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response -> new SimpleResponse<>(response, RemoveParticipantsResponseConstructorProxy.create(response.getValue())));
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ //region Content management Actions
+ /***
+ * Returns an object of CallContentAsync
+ *
+ * @return a CallContentAsync.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public CallMediaAsync getCallMediaAsync() {
+ return new CallMediaAsync(callConnectionId, contentsInternal);
+ }
+ //endregion
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMedia.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMedia.java
new file mode 100644
index 0000000000000..373f3aadb4fc1
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMedia.java
@@ -0,0 +1,128 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.PlayOptions;
+import com.azure.communication.callautomation.models.PlaySource;
+import com.azure.communication.callautomation.models.RecognizeOptions;
+import com.azure.communication.common.CommunicationIdentifier;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.http.rest.Response;
+import com.azure.core.util.Context;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * CallContent.
+ */
+public class CallMedia {
+ private final CallMediaAsync callMediaAsync;
+
+ CallMedia(CallMediaAsync callMediaAsync) {
+ this.callMediaAsync = callMediaAsync;
+ }
+
+ /**
+ * Play
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param playTo the targets to play to.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void play(PlaySource playSource, List playTo) {
+ callMediaAsync.play(playSource, playTo).block();
+ }
+
+ /**
+ * Play to all participants
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void playToAll(PlaySource playSource) {
+ callMediaAsync.playToAll(playSource).block();
+ }
+
+ /**
+ * PlayWithResponse
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param playTo the targets to play to.
+ * @param options play options.
+ * @param context A {@link Context} representing the request context.
+ * @return Response for successful play request.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response playWithResponse(PlaySource playSource, List playTo,
+ PlayOptions options, Context context) {
+ return callMediaAsync.playWithResponseInternal(playSource, playTo, options, context).block();
+ }
+
+ /**
+ * PlayAllWithResponse
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param options play options.
+ * @param context A {@link Context} representing the request context.
+ * @return Response for successful playAll request.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response playToAllWithResponse(PlaySource playSource, PlayOptions options, Context context) {
+ return callMediaAsync
+ .playWithResponseInternal(playSource, Collections.emptyList(), options, context)
+ .block();
+ }
+
+ /**
+ * Recognize tones.
+ * @param recognizeOptions Optional elements for recognize.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void recognize(RecognizeOptions recognizeOptions) {
+ callMediaAsync.recognize(recognizeOptions).block();
+ }
+
+ /**
+ * Recognize tones.
+ * @param recognizeOptions Optional elements for recognize.
+ * @param context A {@link Context} representing the request context.
+ * @return Response for a successful recognize request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response recognizeWithResponse(RecognizeOptions recognizeOptions, Context context) {
+ return callMediaAsync
+ .recognizeWithResponseInternal(recognizeOptions, context)
+ .block();
+ }
+
+ /**
+ * Cancels all the queued media operations.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void cancelAllMediaOperations() {
+ cancelAllMediaOperationsWithResponse(null);
+ }
+
+ /**
+ * Cancels all the queued media operations
+ * @param context A {@link Context} representing the request context.
+ * @return Response for successful playAll request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response cancelAllMediaOperationsWithResponse(Context context) {
+ return callMediaAsync.cancelAllMediaOperationsWithResponseInternal(context).block();
+ }
+
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMediaAsync.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMediaAsync.java
new file mode 100644
index 0000000000000..3cdaa19f0e016
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallMediaAsync.java
@@ -0,0 +1,260 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.implementation.ContentsImpl;
+import com.azure.communication.callautomation.implementation.accesshelpers.ErrorConstructorProxy;
+import com.azure.communication.callautomation.implementation.converters.CommunicationIdentifierConverter;
+import com.azure.communication.callautomation.implementation.models.DtmfConfigurationsInternal;
+import com.azure.communication.callautomation.implementation.models.FileSourceInternal;
+import com.azure.communication.callautomation.implementation.models.PlayOptionsInternal;
+import com.azure.communication.callautomation.implementation.models.PlayRequest;
+import com.azure.communication.callautomation.implementation.models.PlaySourceInternal;
+import com.azure.communication.callautomation.implementation.models.PlaySourceTypeInternal;
+import com.azure.communication.callautomation.implementation.models.RecognizeConfigurationsInternal;
+import com.azure.communication.callautomation.implementation.models.RecognizeInputTypeInternal;
+import com.azure.communication.callautomation.implementation.models.RecognizeRequest;
+import com.azure.communication.callautomation.implementation.models.StopTonesInternal;
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.DtmfConfigurations;
+import com.azure.communication.callautomation.models.FileSource;
+import com.azure.communication.callautomation.models.PlayOptions;
+import com.azure.communication.callautomation.models.PlaySource;
+import com.azure.communication.callautomation.models.RecognizeConfigurations;
+import com.azure.communication.callautomation.models.RecognizeOptions;
+import com.azure.communication.common.CommunicationIdentifier;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.rest.Response;
+import com.azure.core.util.Context;
+import com.azure.core.util.FluxUtil;
+import com.azure.core.util.logging.ClientLogger;
+import reactor.core.publisher.Mono;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.azure.core.util.FluxUtil.monoError;
+import static com.azure.core.util.FluxUtil.withContext;
+
+/**
+ * CallContent.
+ */
+public class CallMediaAsync {
+ private final ContentsImpl contentsInternal;
+ private final String callConnectionId;
+ private final ClientLogger logger;
+
+ CallMediaAsync(String callConnectionId, ContentsImpl contentsInternal) {
+ this.callConnectionId = callConnectionId;
+ this.contentsInternal = contentsInternal;
+ this.logger = new ClientLogger(CallMediaAsync.class);
+ }
+
+ /**
+ * Play
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param playTo the targets to play to
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Void for successful play request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono play(PlaySource playSource, List playTo) {
+ return playWithResponse(playSource, playTo, null).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Play to all participants
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Void for successful playAll request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono playToAll(PlaySource playSource) {
+ return playToAllWithResponse(playSource, null).flatMap(FluxUtil::toMono);
+ }
+
+ /**
+ * Play
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param playTo the targets to play to
+ * @param options play options.
+ * @return Response for successful play request.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> playWithResponse(PlaySource playSource, List playTo,
+ PlayOptions options) {
+ return playWithResponseInternal(playSource, playTo, options, null);
+ }
+
+ /**
+ * Play to all participants
+ *
+ * @param playSource A {@link PlaySource} representing the source to play.
+ * @param options play options.
+ * @return Response for successful playAll request.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> playToAllWithResponse(PlaySource playSource, PlayOptions options) {
+ return playWithResponseInternal(playSource, Collections.emptyList(), options, null);
+ }
+
+ /**
+ * Recognize operation.
+ * @param recognizeOptions Different attributes for recognize.
+ * @return Response for successful recognize request.
+ */
+ public Mono recognize(RecognizeOptions recognizeOptions) {
+ return recognizeWithResponse(recognizeOptions).then();
+ }
+
+ /**
+ * Recognize operation
+ * @param recognizeOptions Different attributes for recognize.
+ * @return Response for successful recognize request.
+ */
+ public Mono> recognizeWithResponse(RecognizeOptions recognizeOptions) {
+ return withContext(context -> recognizeWithResponseInternal(recognizeOptions, context));
+ }
+
+ Mono> recognizeWithResponseInternal(RecognizeOptions recognizeOptions, Context context) {
+ try {
+ context = context == null ? Context.NONE : context;
+
+ RecognizeConfigurations recognizeConfigurations = recognizeOptions.getRecognizeConfiguration();
+ DtmfConfigurationsInternal dtmfConfigurationsInternal = null;
+ if (recognizeConfigurations.getDtmfConfigurations() != null) {
+ DtmfConfigurations dtmfConfigurations = recognizeConfigurations.getDtmfConfigurations();
+ dtmfConfigurationsInternal = new DtmfConfigurationsInternal()
+ .setMaxTonesToCollect(dtmfConfigurations.getMaxTonesToCollect());
+
+ if (dtmfConfigurations.getInterToneTimeoutInSeconds() != null) {
+ dtmfConfigurationsInternal.setInterToneTimeoutInSeconds((int) dtmfConfigurations.getInterToneTimeoutInSeconds().getSeconds());
+ }
+ if (dtmfConfigurations.getStopTones() != null) {
+ dtmfConfigurationsInternal
+ .setStopTones(dtmfConfigurations.getStopTones().stream()
+ .map(stopTones -> StopTonesInternal.fromString(stopTones.toString()))
+ .collect(Collectors.toList()));
+
+ }
+ }
+ RecognizeConfigurationsInternal recognizeConfigurationsInternal = new RecognizeConfigurationsInternal()
+ .setDtmfConfigurations(dtmfConfigurationsInternal)
+ .setInterruptPromptAndStartRecognition(recognizeConfigurations.isInterruptPromptAndStartRecognition())
+ .setTargetParticipant(CommunicationIdentifierConverter.convert(recognizeConfigurations.getTargetParticipant()));
+ if (recognizeConfigurations.getInitialSilenceTimeoutInSeconds() != null) {
+ recognizeConfigurationsInternal.setInitialSilenceTimeoutInSeconds((int) recognizeConfigurations.getInitialSilenceTimeoutInSeconds().getSeconds());
+ }
+
+ PlaySourceInternal playSourceInternal = null;
+ if (recognizeOptions.getPlayPrompt() != null) {
+ PlaySource playSource = recognizeOptions.getPlayPrompt();
+ if (playSource instanceof FileSource) {
+ playSourceInternal = getPlaySourceInternal((FileSource) playSource);
+ }
+ }
+ RecognizeRequest recognizeRequest = new RecognizeRequest()
+ .setRecognizeInputType(RecognizeInputTypeInternal.fromString(recognizeOptions.getRecognizeInputType().toString()))
+ .setRecognizeConfiguration(recognizeConfigurationsInternal)
+ .setStopCurrentOperations(recognizeOptions.isStopCurrentOperations())
+ .setPlayPrompt(playSourceInternal)
+ .setOperationContext(recognizeOptions.getOperationContext());
+
+ return contentsInternal.recognizeWithResponseAsync(callConnectionId, recognizeRequest, context);
+
+ } catch (RuntimeException e) {
+ return monoError(logger, e);
+ }
+ }
+
+ /**
+ * Cancels all the queued media operations.
+ * @return Void
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono cancelAllMediaOperations() {
+ return cancelAllMediaOperationsWithResponse().then();
+ }
+
+ /**
+ * Cancels all the queued media operations
+ * @return Response for successful playAll request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> cancelAllMediaOperationsWithResponse() {
+ return cancelAllMediaOperationsWithResponseInternal(null);
+ }
+
+ Mono> cancelAllMediaOperationsWithResponseInternal(Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return contentsInternal.cancelAllMediaOperationsWithResponseAsync(callConnectionId, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ });
+
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ Mono> playWithResponseInternal(PlaySource playSource, List playTo,
+ PlayOptions options, Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ PlayRequest request = getPlayRequest(playSource, playTo, options);
+ return contentsInternal.playWithResponseAsync(callConnectionId, request, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ });
+
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ PlayRequest getPlayRequest(PlaySource playSource, List playTo, PlayOptions options) {
+ if (playSource instanceof FileSource) {
+ PlaySourceInternal playSourceInternal = getPlaySourceInternal((FileSource) playSource);
+
+ PlayRequest request = new PlayRequest()
+ .setPlaySourceInfo(playSourceInternal)
+ .setPlayTo(
+ playTo
+ .stream()
+ .map(CommunicationIdentifierConverter::convert)
+ .collect(Collectors.toList()));
+
+ if (options != null) {
+ request.setPlayOptions(new PlayOptionsInternal().setLoop(options.isLoop()));
+ request.setOperationContext(options.getOperationContext());
+ }
+
+ return request;
+ }
+
+ throw logger.logExceptionAsError(new IllegalArgumentException(playSource.getClass().getCanonicalName()));
+ }
+
+ private PlaySourceInternal getPlaySourceInternal(FileSource fileSource) {
+ FileSourceInternal fileSourceInternal = new FileSourceInternal().setUri(fileSource.getUri());
+ PlaySourceInternal playSourceInternal = new PlaySourceInternal()
+ .setSourceType(PlaySourceTypeInternal.FILE)
+ .setFileSource(fileSourceInternal)
+ .setPlaySourceId(fileSource.getPlaySourceId());
+ return playSourceInternal;
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecording.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecording.java
new file mode 100644
index 0000000000000..2886c8f87bc0b
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecording.java
@@ -0,0 +1,284 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.DownloadToFileOptions;
+import com.azure.communication.callautomation.models.RecordingStateResult;
+import com.azure.communication.callautomation.models.StartRecordingOptions;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.http.HttpRange;
+import com.azure.core.http.rest.Response;
+import com.azure.core.util.BinaryData;
+import com.azure.core.util.Context;
+
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.security.InvalidParameterException;
+import java.util.Objects;
+
+/**
+ * CallRecording.
+ */
+public class CallRecording {
+ private final CallRecordingAsync callRecordingAsync;
+
+ CallRecording(CallRecordingAsync callRecordingAsync) {
+ this.callRecordingAsync = callRecordingAsync;
+ }
+
+ /**
+ * Start recording of the call.
+ *
+ * @param options A {@link StartRecordingOptions} object containing different options for recording.
+ * @throws InvalidParameterException is recordingStateCallbackUri is absolute uri.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Result for a successful start recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public RecordingStateResult startRecording(StartRecordingOptions options) {
+ return callRecordingAsync.startRecording(options).block();
+ }
+
+ /**
+ * Start recording of the call.
+ *
+ * @param options A {@link StartRecordingOptions} object containing different options for recording.
+ * @param context A {@link Context} representing the request context.
+ * @throws InvalidParameterException is recordingStateCallbackUri is absolute uri.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Result for a successful start recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response startRecordingWithResponse(StartRecordingOptions options, Context context) {
+ return callRecordingAsync.startRecordingWithResponseInternal(options, context).block();
+ }
+
+ /**
+ * Stop recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void stopRecording(String recordingId) {
+ callRecordingAsync.stopRecording(recordingId).block();
+ }
+
+ /**
+ * Stop recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful stop recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response stopRecordingWithResponse(String recordingId, Context context) {
+ return callRecordingAsync.stopRecordingWithResponseInternal(recordingId, context).block();
+ }
+
+ /**
+ * Pause recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void pauseRecording(String recordingId) {
+ callRecordingAsync.pauseRecording(recordingId).block();
+ }
+
+ /**
+ * Pause recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful pause recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response pauseRecordingWithResponse(String recordingId, Context context) {
+ return callRecordingAsync.pauseRecordingWithResponseInternal(recordingId, context).block();
+ }
+
+ /**
+ * Resume recording of the call.
+ *
+ * @param recordingId The recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void resumeRecording(String recordingId) {
+ callRecordingAsync.resumeRecording(recordingId).block();
+ }
+
+ /**
+ * Resume recording of the call.
+ *
+ * @param recordingId The recording id to stop.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful resume recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response resumeRecordingWithResponse(String recordingId, final Context context) {
+ return callRecordingAsync.resumeRecordingWithResponseInternal(recordingId, context).block();
+ }
+
+ /**
+ * Get the current recording state by recording id.
+ *
+ * @param recordingId The recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful get recording state request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public RecordingStateResult getRecordingState(String recordingId) {
+ return callRecordingAsync.getRecordingState(recordingId).block();
+ }
+
+ /**
+ * Get the current recording state by recording id.
+ *
+ * @param recordingId The recording id to stop.
+ * @param context A {@link Context} representing the request context.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful get recording state request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getRecordingStateWithResponse(String recordingId, Context context) {
+ return callRecordingAsync.getRecordingStateWithResponseInternal(recordingId, context).block();
+ }
+
+ /**
+ * Download the recording content, e.g. Recording's metadata, Recording video, etc., from
+ * {@code endpoint} and write it in the {@link OutputStream} passed as parameter.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationStream - A stream where to write the downloaded content.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void downloadTo(String sourceEndpoint, OutputStream destinationStream) {
+ downloadToWithResponse(sourceEndpoint, destinationStream, null, null);
+ }
+
+ /**
+ * Download the recording content, e.g. Recording's metadata, Recording video, etc., from
+ * {@code endpoint} and write it in the {@link OutputStream} passed as parameter.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationStream - A stream where to write the downloaded content.
+ * @param httpRange - An optional {@link HttpRange} value containing the range of bytes to download. If missing,
+ * the whole content will be downloaded.
+ * @param context A {@link Context} representing the request context.
+ * @return Response containing the http response information from the download.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response downloadToWithResponse(String sourceEndpoint,
+ OutputStream destinationStream,
+ HttpRange httpRange,
+ Context context) {
+ Objects.requireNonNull(sourceEndpoint, "'sourceEndpoint' cannot be null");
+ Objects.requireNonNull(destinationStream, "'destinationStream' cannot be null");
+ return callRecordingAsync
+ .downloadToWithResponse(sourceEndpoint, destinationStream, httpRange, context)
+ .block();
+ }
+
+ /**
+ * Downloads the entire content.
+ * This method supports downloads up to 2GB of data.
+ * Use {@link #downloadTo(String, OutputStream)} to download larger blobs.
+ *
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @return The content of the blob.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public BinaryData downloadContent(String sourceEndpoint) {
+ return callRecordingAsync.downloadContent(sourceEndpoint).block();
+ }
+
+ /**
+ * Downloads the entire content.
+ * This method supports downloads up to 2GB of data.
+ * Use {@link #downloadToWithResponse(String, OutputStream, HttpRange, Context)} to download larger blobs.
+ *
+ * @param sourceEndpoint ACS URL where the content is located.
+ * @param range An optional {@link HttpRange} value containing the range of bytes to download. If missing,
+ * the whole content will be downloaded.
+ * @param context A {@link Context} representing the request context.
+ * @return The content of the blob.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response downloadContentWithResponse(String sourceEndpoint, HttpRange range, Context context) {
+ return callRecordingAsync.downloadContentWithResponseInternal(sourceEndpoint, range, context).block();
+ }
+
+ /**
+ * Download the content located in {@code endpoint} into a file marked by {@code path}.
+ * This download will be done using parallel workers.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationPath - File location.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void downloadTo(String sourceEndpoint,
+ Path destinationPath) {
+ DownloadToFileOptions options = new DownloadToFileOptions();
+ downloadToWithResponse(sourceEndpoint, destinationPath, options, null);
+ }
+
+ /**
+ * Download the content located in {@code endpoint} into a file marked by {@code path}.
+ * This download will be done using parallel workers.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationPath - File location.
+ * @param options - an optional {@link DownloadToFileOptions} object to modify how the
+ * download will work.
+ * @param context A {@link Context} representing the request context.
+ * @return Response containing the http response information from the download.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response downloadToWithResponse(String sourceEndpoint,
+ Path destinationPath,
+ DownloadToFileOptions options,
+ final Context context) {
+ Objects.requireNonNull(sourceEndpoint, "'sourceEndpoint' cannot be null");
+ Objects.requireNonNull(destinationPath, "'destinationPath' cannot be null");
+ return callRecordingAsync.downloadToWithResponseInternal(sourceEndpoint, destinationPath,
+ options, context).block();
+ }
+
+ /**
+ * Delete the content located in the deleteEndpoint
+ *
+ * @param deleteEndpoint - ACS URL where the content is located.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void deleteRecording(String deleteEndpoint) {
+ deleteRecordingWithResponse(deleteEndpoint, null);
+ }
+
+ /**
+ * Delete the content located in the deleteEndpoint
+ *
+ * @param deleteEndpoint - ACS URL where the content is located.
+ * @param context A {@link Context} representing the request context.
+ * @return Response for successful delete request..
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response deleteRecordingWithResponse(String deleteEndpoint, Context context) {
+ return callRecordingAsync.deleteRecordingWithResponseInternal(deleteEndpoint, context).block();
+ }
+
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecordingAsync.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecordingAsync.java
new file mode 100644
index 0000000000000..51989c18e90b1
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallRecordingAsync.java
@@ -0,0 +1,571 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.implementation.ContentsImpl;
+import com.azure.communication.callautomation.implementation.ServerCallsImpl;
+import com.azure.communication.callautomation.implementation.accesshelpers.ErrorConstructorProxy;
+import com.azure.communication.callautomation.implementation.accesshelpers.RecordingStateResponseConstructorProxy;
+import com.azure.communication.callautomation.implementation.converters.CommunicationIdentifierConverter;
+import com.azure.communication.callautomation.implementation.models.CallLocatorInternal;
+import com.azure.communication.callautomation.implementation.models.CallLocatorKindInternal;
+import com.azure.communication.callautomation.implementation.models.ChannelAffinityInternal;
+import com.azure.communication.callautomation.implementation.models.RecordingContentInternal;
+import com.azure.communication.callautomation.implementation.models.RecordingFormatInternal;
+import com.azure.communication.callautomation.implementation.models.RecordingChannelInternal;
+import com.azure.communication.callautomation.implementation.models.StartCallRecordingRequestInternal;
+import com.azure.communication.callautomation.models.CallLocator;
+import com.azure.communication.callautomation.models.CallLocatorKind;
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.DownloadToFileOptions;
+import com.azure.communication.callautomation.models.GroupCallLocator;
+import com.azure.communication.callautomation.models.ParallelDownloadOptions;
+import com.azure.communication.callautomation.models.RecordingStateResult;
+import com.azure.communication.callautomation.models.ServerCallLocator;
+import com.azure.communication.callautomation.models.StartRecordingOptions;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.HttpRange;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.SimpleResponse;
+import com.azure.core.util.BinaryData;
+import com.azure.core.util.Context;
+import com.azure.core.util.logging.ClientLogger;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.security.InvalidParameterException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.azure.core.util.FluxUtil.monoError;
+import static com.azure.core.util.FluxUtil.withContext;
+
+/**
+ * CallRecordingAsync.
+ */
+public class CallRecordingAsync {
+ private final ServerCallsImpl serverCallsInternal;
+ private final ContentsImpl contentsInternal;
+ private final ClientLogger logger;
+ private final ContentDownloader contentDownloader;
+ private final HttpPipeline httpPipelineInternal;
+ private final String resourceEndpoint;
+
+ CallRecordingAsync(ServerCallsImpl serverCallsInternal, ContentsImpl contentsInternal,
+ ContentDownloader contentDownloader, HttpPipeline httpPipelineInternal, String resourceEndpoint) {
+ this.serverCallsInternal = serverCallsInternal;
+ this.contentsInternal = contentsInternal;
+ this.contentDownloader = contentDownloader;
+ this.httpPipelineInternal = httpPipelineInternal;
+ this.resourceEndpoint = resourceEndpoint;
+ this.logger = new ClientLogger(CallRecordingAsync.class);
+ }
+
+ /**
+ * Start recording of the call.
+ *
+ * @param options A {@link StartRecordingOptions} object containing different options for recording.
+ * @throws InvalidParameterException is recordingStateCallbackUri is absolute uri.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful start recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono startRecording(StartRecordingOptions options) {
+ return startRecordingWithResponse(options)
+ .flatMap(response -> Mono.just(response.getValue()));
+ }
+
+ /**
+ * Start recording of the call.
+ *
+ * @param options A {@link StartRecordingOptions} object containing different options for recording.
+ * @throws InvalidParameterException is recordingStateCallbackUri is absolute uri.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful start recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> startRecordingWithResponse(StartRecordingOptions options) {
+ Objects.requireNonNull(options, "'options' cannot be null.");
+
+ return startRecordingWithResponseInternal(options, null);
+ }
+
+ Mono> startRecordingWithResponseInternal(StartRecordingOptions options, Context context) {
+ try {
+ String callbackUrl = options.getRecordingStateCallbackUrl();
+ if (callbackUrl != null && !callbackUrl.isEmpty() && !Boolean.TRUE.equals(new URI(callbackUrl).isAbsolute())) {
+ throw logger.logExceptionAsError(new InvalidParameterException("'recordingStateCallbackUri' has to be an absolute Uri"));
+ }
+ StartCallRecordingRequestInternal request = getStartCallRecordingRequest(options);
+
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return contentsInternal
+ .recordingWithResponseAsync(request, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response ->
+ new SimpleResponse<>(response, RecordingStateResponseConstructorProxy.create(response.getValue()))
+ );
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ } catch (URISyntaxException ex) {
+ return monoError(logger, new RuntimeException(ex));
+ }
+ }
+
+ private StartCallRecordingRequestInternal getStartCallRecordingRequest(StartRecordingOptions options) {
+ CallLocator callLocator = options.getCallLocator();
+ CallLocatorInternal callLocatorInternal = new CallLocatorInternal()
+ .setKind(CallLocatorKindInternal.fromString(callLocator.getKind().toString()));
+
+ if (callLocator.getKind() == CallLocatorKind.GROUP_CALL_LOCATOR) {
+ callLocatorInternal.setGroupCallId(((GroupCallLocator) callLocator).getGroupCallId());
+ } else if (callLocator.getKind() == CallLocatorKind.SERVER_CALL_LOCATOR) {
+ callLocatorInternal.setServerCallId(((ServerCallLocator) callLocator).getServerCallId());
+ } else {
+ throw logger.logExceptionAsError(new InvalidParameterException("callLocator has invalid kind."));
+ }
+
+ StartCallRecordingRequestInternal request = new StartCallRecordingRequestInternal()
+ .setCallLocator(callLocatorInternal);
+
+ if (options.getRecordingContent() != null) {
+ request.setRecordingContentType(RecordingContentInternal.fromString(options.getRecordingContent().toString()));
+ }
+ if (options.getRecordingFormat() != null) {
+ request.setRecordingFormatType(RecordingFormatInternal.fromString(options.getRecordingFormat().toString()));
+ }
+ if (options.getRecordingChannel() != null) {
+ request.setRecordingChannelType(RecordingChannelInternal.fromString(options.getRecordingChannel().toString()));
+ }
+ if (options.getRecordingStateCallbackUrl() != null) {
+ request.setRecordingStateCallbackUri(options.getRecordingStateCallbackUrl());
+ }
+ if (options.getChannelAffinity() != null) {
+ List channelAffinityInternal = options.getChannelAffinity()
+ .stream()
+ .map(c -> new ChannelAffinityInternal()
+ .setChannel(c.getChannel())
+ .setParticipant(CommunicationIdentifierConverter.convert(c.getParticipant())))
+ .collect(Collectors.toList());
+ request.setChannelAffinity(channelAffinityInternal);
+ }
+
+ return request;
+ }
+
+ /**
+ * Stop recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful stop recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono stopRecording(String recordingId) {
+ return stopRecordingWithResponse(recordingId).then();
+ }
+
+ /**
+ * Stop recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful stop recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> stopRecordingWithResponse(String recordingId) {
+ return stopRecordingWithResponseInternal(recordingId, null);
+ }
+
+ Mono> stopRecordingWithResponseInternal(String recordingId, Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return serverCallsInternal
+ .stopRecordingWithResponseAsync(recordingId, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Pause recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful pause recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono pauseRecording(String recordingId) {
+ return pauseRecordingWithResponse(recordingId).then();
+ }
+
+ /**
+ * Pause recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful pause recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> pauseRecordingWithResponse(String recordingId) {
+ return pauseRecordingWithResponseInternal(recordingId, null);
+ }
+
+ Mono> pauseRecordingWithResponseInternal(String recordingId, Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return serverCallsInternal
+ .pauseRecordingWithResponseAsync(recordingId, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Resume recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return response for a successful resume recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono resumeRecording(String recordingId) {
+ return resumeRecordingWithResponse(recordingId).then();
+ }
+
+ /**
+ * Resume recording of the call.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return response for a successful resume recording request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> resumeRecordingWithResponse(String recordingId) {
+ return resumeRecordingWithResponseInternal(recordingId, null);
+ }
+
+ Mono> resumeRecordingWithResponseInternal(String recordingId, Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return serverCallsInternal
+ .resumeRecordingWithResponseAsync(recordingId, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create);
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Get current recording state by recording id.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful get recording state request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getRecordingState(String recordingId) {
+ return getRecordingStateWithResponse(recordingId).flatMap(response -> Mono.just(response.getValue()));
+ }
+
+ /**
+ * Get current recording state by recording id.
+ *
+ * @param recordingId Recording id to stop.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for a successful get recording state request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getRecordingStateWithResponse(String recordingId) {
+ return getRecordingStateWithResponseInternal(recordingId, null);
+ }
+
+ Mono> getRecordingStateWithResponseInternal(String recordingId, Context context) {
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return serverCallsInternal
+ .getRecordingPropertiesWithResponseAsync(recordingId, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response ->
+ new SimpleResponse<>(response, RecordingStateResponseConstructorProxy.create(response.getValue())));
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Download the recording content, e.g. Recording's metadata, Recording video, from the ACS endpoint
+ * passed as parameter.
+ * @param sourceEndpoint - URL where the content is located.
+ * @return A {@link Flux} object containing the byte stream of the content requested.
+ */
+ @ServiceMethod(returns = ReturnType.COLLECTION)
+ public Flux downloadStream(String sourceEndpoint) {
+ return downloadStreamWithResponse(sourceEndpoint, null)
+ .map(Response::getValue)
+ .flux()
+ .flatMap(flux -> flux);
+ }
+
+ /**
+ * Download the recording content, (e.g. Recording's metadata, Recording video, etc.) from the {@code endpoint}.
+ * @param sourceEndpoint - URL where the content is located.
+ * @param range - An optional {@link HttpRange} value containing the range of bytes to download. If missing,
+ * the whole content will be downloaded.
+ * @return A {@link Mono} object containing a {@link Response} with the byte stream of the content requested.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono>> downloadStreamWithResponse(String sourceEndpoint, HttpRange range) {
+ return downloadStreamWithResponseInternal(sourceEndpoint, range, null);
+ }
+
+ Mono>> downloadStreamWithResponseInternal(String sourceEndpoint, HttpRange range, Context context) {
+ try {
+ Objects.requireNonNull(sourceEndpoint, "'sourceEndpoint' cannot be null");
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return contentDownloader.downloadStreamWithResponse(sourceEndpoint, range, contextValue);
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Reads the entire content.
+ *
+ * Code Samples
+ *
+ * This method supports downloads up to 2GB of data.
+ * Use {@link #downloadStream(String)} ()} to download larger blobs.
+ *
+ * @param sourceEndpoint - URL where the content is located.
+ * @return A reactive response containing the content data.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono downloadContent(String sourceEndpoint) {
+ return downloadStreamWithResponse(sourceEndpoint, null)
+ .flatMap(response -> BinaryData.fromFlux(response.getValue()));
+ }
+
+ /**
+ * Reads a range of bytes from a content.
+ *
+ * This method supports downloads up to 2GB of data.
+ * Use {@link #downloadStreamWithResponse(String, HttpRange)}
+ * to download larger blobs.
+ *
+ * @param sourceEndpoint - URL where the content is located.
+ * @param range - An optional {@link HttpRange} value containing the range of bytes to download. If missing,
+ * the whole content will be downloaded.
+ * @return A reactive response containing the blob data.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> downloadContentWithResponse(String sourceEndpoint, HttpRange range) {
+ return downloadContentWithResponseInternal(sourceEndpoint, range, null);
+ }
+
+ Mono> downloadContentWithResponseInternal(String sourceEndpoint, HttpRange range, Context context) {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return downloadStreamWithResponseInternal(sourceEndpoint, range, contextValue)
+ .flatMap(response -> BinaryData.fromFlux(response.getValue())
+ .map(data -> new SimpleResponse<>(response.getRequest(), response.getStatusCode(),
+ response.getHeaders(), data)));
+ });
+ }
+
+ /**
+ * Download the content located in {@code endpoint} into a file marked by {@code path}.
+ * This download will be done using parallel workers.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationPath - File location.
+ * @return Response for a successful downloadTo request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono downloadTo(
+ String sourceEndpoint,
+ Path destinationPath) {
+ try {
+ DownloadToFileOptions options = new DownloadToFileOptions();
+ return downloadToWithResponse(sourceEndpoint, destinationPath, options).then();
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Download the content located in {@code endpoint} into a file marked by {@code path}.
+ * This download will be done using parallel workers.
+ * @param sourceEndpoint - ACS URL where the content is located.
+ * @param destinationPath - File location.
+ * @param options - an optional {@link DownloadToFileOptions} object to modify how the
+ * download will work.
+ * @return Response containing the http response information from the download.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> downloadToWithResponse(
+ String sourceEndpoint,
+ Path destinationPath,
+ DownloadToFileOptions options) {
+ return downloadToWithResponseInternal(sourceEndpoint, destinationPath, options, null);
+ }
+
+ Mono> downloadToWithResponseInternal(
+ String sourceEndpoint,
+ Path destinationPath,
+ DownloadToFileOptions options,
+ Context context) {
+ Objects.requireNonNull(sourceEndpoint, "'sourceEndpoint' cannot be null");
+ Objects.requireNonNull(destinationPath, "'destinationPath' cannot be null");
+
+ Set openOptions = new HashSet<>();
+
+ if (options.isOverwrite()) {
+ openOptions.add(StandardOpenOption.CREATE);
+ } else {
+ openOptions.add(StandardOpenOption.CREATE_NEW);
+ }
+ openOptions.add(StandardOpenOption.WRITE);
+
+ try {
+ AsynchronousFileChannel file = AsynchronousFileChannel.open(destinationPath, openOptions, null);
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ return downloadToWithResponse(sourceEndpoint, destinationPath, file, options, contextValue);
+ });
+ } catch (IOException ex) {
+ return monoError(logger, new RuntimeException(ex));
+ }
+ }
+
+ Mono> downloadToWithResponse(
+ String sourceEndpoint,
+ OutputStream destinationStream,
+ HttpRange httpRange,
+ Context context) {
+
+ return contentDownloader.downloadToStreamWithResponse(sourceEndpoint, destinationStream, httpRange, context);
+ }
+
+ Mono> downloadToWithResponse(
+ String sourceEndpoint,
+ Path destinationPath,
+ AsynchronousFileChannel fileChannel,
+ DownloadToFileOptions options,
+ Context context
+ ) {
+ ParallelDownloadOptions finalParallelDownloadOptions =
+ options.getParallelDownloadOptions() == null
+ ? new ParallelDownloadOptions()
+ : options.getParallelDownloadOptions();
+
+ return Mono.just(fileChannel).flatMap(
+ c -> contentDownloader.downloadToFileWithResponse(sourceEndpoint, c, finalParallelDownloadOptions, context))
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .doFinally(signalType -> contentDownloader.downloadToFileCleanup(fileChannel, destinationPath, signalType));
+ }
+
+ /**
+ * Delete the content located at the deleteEndpoint
+ * @param deleteEndpoint - ACS URL where the content is located.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return Response for successful delete request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono deleteRecording(String deleteEndpoint) {
+ try {
+ return deleteRecordingWithResponseInternal(deleteEndpoint, null)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .then();
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ /**
+ * Delete the content located at the deleteEndpoint
+ * Recording deletion will be done using parallel workers.
+ * @param deleteEndpoint - ACS URL where the content is located.
+ * @throws CallingServerErrorException thrown if the request is rejected by server.
+ * @return Response for successful delete request.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> deleteRecordingWithResponse(String deleteEndpoint) {
+ return deleteRecordingWithResponseInternal(deleteEndpoint, null);
+ }
+
+ Mono> deleteRecordingWithResponseInternal(String deleteEndpoint, Context context) {
+ HttpRequest request = new HttpRequest(HttpMethod.DELETE, deleteEndpoint);
+ URL urlToSignWith = getUrlToSignRequestWith(deleteEndpoint);
+ try {
+ return withContext(contextValue -> {
+ contextValue = context == null ? contextValue : context;
+ contextValue = contextValue.addData("hmacSignatureURL", urlToSignWith);
+ return httpPipelineInternal
+ .send(request, contextValue)
+ .onErrorMap(HttpResponseException.class, ErrorConstructorProxy::create)
+ .map(response -> new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), null));
+ });
+ } catch (RuntimeException ex) {
+ return monoError(logger, ex);
+ }
+ }
+
+ private URL getUrlToSignRequestWith(String endpoint) {
+ try {
+ String path = new URL(endpoint).getPath();
+
+ if (path.startsWith("/")) {
+ path = path.substring(1);
+ }
+
+ return new URL(resourceEndpoint + path);
+ } catch (MalformedURLException ex) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(ex));
+ }
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallingServerServiceVersion.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallingServerServiceVersion.java
new file mode 100644
index 0000000000000..1d8a42397f9b0
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallingServerServiceVersion.java
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.core.util.ServiceVersion;
+
+/**
+ * Versions of CallingServer service supported by this client library.
+ */
+public enum CallingServerServiceVersion implements ServiceVersion {
+ /**
+ * Service version {@code 2022-04-07-preview}.
+ */
+ V2022_04_07_PREVIEW("2022-04-07-preview"),
+ /**
+ * Service version {@code 2021-11-15-preview}.
+ */
+ V2021_11_15_PREVIEW("2021-11-15-preview");
+
+ private final String version;
+
+ CallingServerServiceVersion(String version) {
+ this.version = version;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getVersion() {
+ return this.version;
+ }
+
+ /**
+ * Gets the latest service version supported by this client library
+ *
+ * @return The latest {@link CallingServerServiceVersion} object.
+ */
+ public static CallingServerServiceVersion getLatest() {
+ return V2022_04_07_PREVIEW;
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/ContentDownloader.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/ContentDownloader.java
new file mode 100644
index 0000000000000..9b82a58660461
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/ContentDownloader.java
@@ -0,0 +1,300 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.implementation.Constants;
+import com.azure.communication.callautomation.implementation.accesshelpers.ErrorConstructorProxy;
+import com.azure.communication.callautomation.models.CallingServerErrorException;
+import com.azure.communication.callautomation.models.ParallelDownloadOptions;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.HttpRange;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.SimpleResponse;
+import com.azure.core.util.Context;
+import com.azure.core.util.FluxUtil;
+import com.azure.core.util.ProgressListener;
+import com.azure.core.util.ProgressReporter;
+import com.azure.core.util.logging.ClientLogger;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.core.publisher.SignalType;
+import reactor.core.scheduler.Schedulers;
+import reactor.util.function.Tuple2;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.function.Function;
+
+import static java.lang.StrictMath.toIntExact;
+
+class ContentDownloader {
+ private final String resourceEndpoint;
+ private final HttpPipeline httpPipeline;
+ private final ClientLogger logger = new ClientLogger(ContentDownloader.class);
+
+ ContentDownloader(String resourceEndpoint, HttpPipeline httpPipeline) {
+ this.resourceEndpoint = resourceEndpoint;
+ this.httpPipeline = httpPipeline;
+ }
+
+ Mono> downloadToStreamWithResponse(
+ String sourceEndpoint,
+ OutputStream destinationStream,
+ HttpRange httpRange,
+ Context context) {
+ return downloadStreamWithResponse(sourceEndpoint, httpRange, context)
+ .flatMap(response -> FluxUtil.writeToOutputStream(response.getValue(), destinationStream)
+ .thenReturn(new SimpleResponse<>(response.getRequest(), response.getStatusCode(),
+ response.getHeaders(), null)));
+ }
+
+ Mono>> downloadStreamWithResponse(
+ String sourceEndpoint,
+ HttpRange httpRange,
+ Context context) {
+ Mono httpResponse = makeDownloadRequest(sourceEndpoint, httpRange, context);
+ return httpResponse.map(response -> {
+ Flux result = getFluxStream(response, sourceEndpoint, httpRange, context);
+ return new SimpleResponse<>(response.getRequest(), response.getStatusCode(),
+ response.getHeaders(), result);
+ });
+ }
+
+ Mono> downloadToFileWithResponse(
+ String sourceEndpoint,
+ AsynchronousFileChannel destinationFile,
+ ParallelDownloadOptions parallelDownloadOptions,
+ Context context) {
+
+ Function>>> downloadFunc =
+ range -> downloadStreamWithResponse(sourceEndpoint, range, context);
+
+ return downloadFirstChunk(parallelDownloadOptions, downloadFunc)
+ .flatMap(setupTuple2 -> {
+ long newCount = setupTuple2.getT1();
+ int numChunks = calculateNumBlocks(newCount, parallelDownloadOptions.getBlockSize());
+
+ // In case it is an empty blob, this ensures we still actually perform a download operation.
+ numChunks = numChunks == 0 ? 1 : numChunks;
+
+ Response> initialResponse = setupTuple2.getT2();
+ ProgressListener progressListener = parallelDownloadOptions.getProgressListener();
+ ProgressReporter progressReporter =
+ progressListener == null
+ ? null
+ : ProgressReporter.withProgressListener(progressListener);
+ return Flux.range(0, numChunks)
+ .flatMap(chunkNum -> downloadChunk(chunkNum, initialResponse,
+ parallelDownloadOptions, newCount, downloadFunc,
+ response ->
+ writeBodyToFile(response, destinationFile, chunkNum, parallelDownloadOptions,
+ progressReporter == null ? null : progressReporter.createChild()).flux()))
+ .then(Mono.just(new SimpleResponse<>(initialResponse, null)));
+ });
+ }
+
+ private Flux getFluxStream(
+ HttpResponse httpResponse,
+ String sourceEndpoint,
+ HttpRange httpRange,
+ Context context) {
+ return FluxUtil.createRetriableDownloadFlux(
+ () -> getResponseBody(httpResponse),
+ (Throwable throwable, Long aLong) -> {
+ if (throwable instanceof CallingServerErrorException) {
+ CallingServerErrorException exception = (CallingServerErrorException) throwable;
+ if (exception.getResponse().getStatusCode() == 416) {
+ return makeDownloadRequest(sourceEndpoint, null, context)
+ .map(this::getResponseBody)
+ .flux()
+ .flatMap(flux -> flux);
+ }
+ }
+
+ HttpRange range;
+ if (httpRange != null) {
+ range = new HttpRange(aLong + 1, httpRange.getLength() - aLong - 1);
+ } else {
+ range = new HttpRange(aLong + 1);
+ }
+
+ return makeDownloadRequest(sourceEndpoint, range, context)
+ .map(this::getResponseBody)
+ .flux()
+ .flatMap(flux -> flux);
+ },
+ Constants.ContentDownloader.MAX_RETRIES
+ );
+ }
+
+ private Flux getResponseBody(HttpResponse response) {
+ switch (response.getStatusCode()) {
+ case 200:
+ case 206:
+ return response.getBody();
+ case 416: // Retriable with new HttpRange, potentially bytes=0-
+ return FluxUtil.fluxError(logger,
+ ErrorConstructorProxy.create(new HttpResponseException(formatExceptionMessage(response), response))
+ );
+ default:
+ throw logger.logExceptionAsError(
+ ErrorConstructorProxy.create(new HttpResponseException(formatExceptionMessage(response), response))
+ );
+ }
+ }
+
+ private String formatExceptionMessage(HttpResponse httpResponse) {
+ return String.format("Service Request failed!%nStatus: %s", httpResponse.getStatusCode());
+ }
+
+ private Mono makeDownloadRequest(
+ String sourceEndpoint,
+ HttpRange httpRange,
+ Context context) {
+ HttpRequest request = getHttpRequest(sourceEndpoint, httpRange);
+ URL urlToSignWith = getUrlToSignRequestWith(sourceEndpoint);
+
+ Context finalContext;
+ if (context == null) {
+ finalContext = new Context("hmacSignatureURL", urlToSignWith);
+ } else {
+ finalContext = context.addData("hmacSignatureURL", urlToSignWith);
+ }
+
+ return httpPipeline.send(request, finalContext);
+ }
+
+ private URL getUrlToSignRequestWith(String endpoint) {
+ try {
+ String path = new URL(endpoint).getPath();
+
+ if (path.startsWith("/")) {
+ path = path.substring(1);
+ }
+
+ return new URL(resourceEndpoint + path);
+ } catch (MalformedURLException ex) {
+ throw logger.logExceptionAsError(new IllegalArgumentException(ex));
+ }
+ }
+
+ private HttpRequest getHttpRequest(String sourceEndpoint, HttpRange httpRange) {
+ HttpRequest request = new HttpRequest(HttpMethod.GET, sourceEndpoint);
+
+ if (null != httpRange) {
+ request.setHeader(Constants.HeaderNames.RANGE, httpRange.toString());
+ }
+
+ return request;
+ }
+
+ private Mono>>> downloadFirstChunk(
+ ParallelDownloadOptions parallelDownloadOptions,
+ Function>>> downloader) {
+ return downloader.apply(new HttpRange(0, parallelDownloadOptions.getBlockSize()))
+ .subscribeOn(Schedulers.boundedElastic())
+ .flatMap(response -> {
+ // Extract the total length of the blob from the contentRange header. e.g. "bytes 1-6/7"
+ long totalLength = extractTotalBlobLength(
+ response.getHeaders().getValue(Constants.HeaderNames.CONTENT_RANGE)
+ );
+
+ return Mono.zip(Mono.just(totalLength), Mono.just(response));
+ });
+ }
+
+ private long extractTotalBlobLength(String contentRange) {
+ return contentRange == null ? 0 : Long.parseLong(contentRange.split("/")[1]);
+ }
+
+ private int calculateNumBlocks(long dataSize, long blockLength) {
+ // Can successfully cast to an int because MaxBlockSize is an int, which this expression must be less than.
+ int numBlocks = toIntExact(dataSize / blockLength);
+ // Include an extra block for trailing data.
+ if (dataSize % blockLength != 0) {
+ numBlocks++;
+ }
+ return numBlocks;
+ }
+
+ private Flux downloadChunk(
+ Integer chunkNum,
+ Response> initialResponse,
+ ParallelDownloadOptions parallelDownloadOptions,
+ long newCount,
+ Function>>> downloader,
+ Function>, Flux> returnTransformer) {
+ if (chunkNum == 0) {
+ return returnTransformer.apply(initialResponse);
+ }
+
+ // Calculate whether we need a full chunk or something smaller because we are at the end.
+ long modifier = chunkNum.longValue() * parallelDownloadOptions.getBlockSize();
+ long chunkSizeActual = Math.min(parallelDownloadOptions.getBlockSize(),
+ newCount - modifier);
+ HttpRange chunkRange = new HttpRange(modifier, chunkSizeActual);
+
+ // Make the download call.
+ return downloader.apply(chunkRange)
+ .subscribeOn(Schedulers.boundedElastic())
+ .flatMapMany(returnTransformer);
+ }
+
+ private static Mono writeBodyToFile(
+ Response> response,
+ AsynchronousFileChannel file,
+ long chunkNum,
+ ParallelDownloadOptions parallelDownloadOptions,
+ ProgressReporter progressReporter) {
+ // Extract the body.
+ Flux data = response.getValue();
+
+ // Report progress as necessary.
+ if (progressReporter != null) {
+ data = addProgressReporting(data, progressReporter);
+ }
+
+ // Write to the file.
+ return FluxUtil.writeFile(data, file, chunkNum * parallelDownloadOptions.getBlockSize());
+ }
+
+ private static Flux addProgressReporting(Flux data, ProgressReporter progressReporter) {
+ return Mono.just(progressReporter).flatMapMany(reporter -> {
+ /*
+ Each time there is a new subscription, we will rewind the progress. This is desirable specifically
+ for retries, which resubscribe on each try. The first time this Flux is subscribed to, the
+ rewind will be a noop as there will have been no progress made. Subsequent rewinds will work as
+ expected.
+ */
+ reporter.reset();
+
+ /*
+ Every time we emit some data, report it to the Tracker, which will pass it on to the end user.
+ */
+ return data.doOnNext(buffer -> progressReporter.reportProgress(buffer.remaining()));
+ });
+ }
+
+ void downloadToFileCleanup(AsynchronousFileChannel channel, Path filePath, SignalType signalType) {
+ try {
+ channel.close();
+ if (!signalType.equals(SignalType.ON_COMPLETE)) {
+ Files.deleteIfExists(filePath);
+ logger.verbose("Downloading to file failed. Cleaning up resources.");
+ }
+ } catch (IOException e) {
+ throw logger.logExceptionAsError(new UncheckedIOException(e));
+ }
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/EventHandler.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/EventHandler.java
new file mode 100644
index 0000000000000..0219fe101eaa2
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/EventHandler.java
@@ -0,0 +1,121 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation;
+
+import com.azure.communication.callautomation.models.events.AddParticipantsFailedEvent;
+import com.azure.communication.callautomation.models.events.AddParticipantsSucceededEvent;
+import com.azure.communication.callautomation.models.events.CallAutomationEventBase;
+import com.azure.communication.callautomation.models.events.CallConnectedEvent;
+import com.azure.communication.callautomation.models.events.CallDisconnectedEvent;
+import com.azure.communication.callautomation.models.events.CallTransferAcceptedEvent;
+import com.azure.communication.callautomation.models.events.CallTransferFailedEvent;
+import com.azure.communication.callautomation.models.events.ParticipantsUpdatedEvent;
+import com.azure.communication.callautomation.models.events.PlayCompleted;
+import com.azure.communication.callautomation.models.events.PlayFailed;
+import com.azure.communication.callautomation.models.events.RecordingStateChangedEvent;
+import com.azure.core.models.CloudEvent;
+import com.azure.core.util.logging.ClientLogger;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+
+/**
+ * Event handler for taking care of event related tasks.
+ */
+public final class EventHandler {
+ private static final ClientLogger LOGGER = new ClientLogger(EventHandler.class);
+
+ /***
+ * Returns a list of events from request's body.
+ *
+ * @param requestBody Body of the event request.
+ * @throws RuntimeException Any exceptions occurs at runtime.
+ * @return a list of CallAutomationEventBase
+ */
+ public static List parseEventList(String requestBody) {
+ List callAutomationBaseEvents;
+ callAutomationBaseEvents = parseCloudEventList(requestBody);
+
+ return callAutomationBaseEvents;
+ }
+
+ /***
+ * Returns the first(or the only) event of request's body.
+ *
+ * @param requestBody Body of the event request.
+ * @throws RuntimeException Any exceptions occurs at runtime.
+ * @return the first(or the only) event if request is not empty, otherwise null is returned.
+ */
+ public static CallAutomationEventBase parseEvent(String requestBody) {
+ List callAutomationBaseEvents = parseEventList(requestBody);
+ return callAutomationBaseEvents.isEmpty() ? null : callAutomationBaseEvents.get(0);
+ }
+
+ private static List parseCloudEventList(String requestBody) {
+ try {
+ List cloudEvents;
+ List callAutomationBaseEvents = new ArrayList<>();
+
+ try {
+ cloudEvents = CloudEvent.fromString(requestBody);
+ } catch (RuntimeException e) {
+ return callAutomationBaseEvents;
+ }
+
+ for (CloudEvent cloudEvent : cloudEvents) {
+ CallAutomationEventBase temp = parseSingleCloudEvent(cloudEvent.getData().toString(), cloudEvent.getType());
+ if (temp != null) {
+ callAutomationBaseEvents.add(temp);
+ }
+ }
+ return callAutomationBaseEvents;
+ } catch (RuntimeException e) {
+ throw LOGGER.logExceptionAsError(e);
+ }
+ }
+
+ private static CallAutomationEventBase parseSingleCloudEvent(String data, String eventType) {
+ try {
+ CallAutomationEventBase ret = null;
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+
+ JsonNode eventData = mapper.readTree(data);
+
+ if (Objects.equals(eventType, "Microsoft.Communication.CallConnected")) {
+ ret = mapper.convertValue(eventData, CallConnectedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.CallDisconnected")) {
+ ret = mapper.convertValue(eventData, CallDisconnectedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.AddParticipantsFailed")) {
+ ret = mapper.convertValue(eventData, AddParticipantsFailedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.AddParticipantsSucceeded")) {
+ ret = mapper.convertValue(eventData, AddParticipantsSucceededEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.CallTransferAccepted")) {
+ ret = mapper.convertValue(eventData, CallTransferAcceptedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.CallTransferFailed")) {
+ ret = mapper.convertValue(eventData, CallTransferFailedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.ParticipantsUpdated")) {
+ ret = mapper.convertValue(eventData, ParticipantsUpdatedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.CallRecordingStateChanged")) {
+ ret = mapper.convertValue(eventData, RecordingStateChangedEvent.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.PlayCompleted")) {
+ ret = mapper.convertValue(eventData, PlayCompleted.class);
+ } else if (Objects.equals(eventType, "Microsoft.Communication.PlayFailed")) {
+ ret = mapper.convertValue(eventData, PlayFailed.class);
+ }
+
+ return ret;
+ } catch (RuntimeException e) {
+ throw LOGGER.logExceptionAsError(e);
+ } catch (JsonProcessingException e) {
+ throw LOGGER.logExceptionAsError(new RuntimeException(e));
+ }
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImpl.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImpl.java
new file mode 100644
index 0000000000000..8d21fe19dd955
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImpl.java
@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+// Code generated by Microsoft (R) AutoRest Code Generator.
+
+package com.azure.communication.callautomation.implementation;
+
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.HttpPipelineBuilder;
+import com.azure.core.http.policy.CookiePolicy;
+import com.azure.core.http.policy.RetryPolicy;
+import com.azure.core.http.policy.UserAgentPolicy;
+import com.azure.core.util.serializer.JacksonAdapter;
+import com.azure.core.util.serializer.SerializerAdapter;
+
+/** Initializes a new instance of the AzureCommunicationCallAutomationService type. */
+public final class AzureCommunicationCallAutomationServiceImpl {
+ /** The endpoint of the Azure Communication resource. */
+ private final String endpoint;
+
+ /**
+ * Gets The endpoint of the Azure Communication resource.
+ *
+ * @return the endpoint value.
+ */
+ public String getEndpoint() {
+ return this.endpoint;
+ }
+
+ /** Api Version. */
+ private final String apiVersion;
+
+ /**
+ * Gets Api Version.
+ *
+ * @return the apiVersion value.
+ */
+ public String getApiVersion() {
+ return this.apiVersion;
+ }
+
+ /** The HTTP pipeline to send requests through. */
+ private final HttpPipeline httpPipeline;
+
+ /**
+ * Gets The HTTP pipeline to send requests through.
+ *
+ * @return the httpPipeline value.
+ */
+ public HttpPipeline getHttpPipeline() {
+ return this.httpPipeline;
+ }
+
+ /** The serializer to serialize an object into a string. */
+ private final SerializerAdapter serializerAdapter;
+
+ /**
+ * Gets The serializer to serialize an object into a string.
+ *
+ * @return the serializerAdapter value.
+ */
+ public SerializerAdapter getSerializerAdapter() {
+ return this.serializerAdapter;
+ }
+
+ /** The ServerCallingsImpl object to access its operations. */
+ private final ServerCallingsImpl serverCallings;
+
+ /**
+ * Gets the ServerCallingsImpl object to access its operations.
+ *
+ * @return the ServerCallingsImpl object.
+ */
+ public ServerCallingsImpl getServerCallings() {
+ return this.serverCallings;
+ }
+
+ /** The CallConnectionsImpl object to access its operations. */
+ private final CallConnectionsImpl callConnections;
+
+ /**
+ * Gets the CallConnectionsImpl object to access its operations.
+ *
+ * @return the CallConnectionsImpl object.
+ */
+ public CallConnectionsImpl getCallConnections() {
+ return this.callConnections;
+ }
+
+ /** The ContentsImpl object to access its operations. */
+ private final ContentsImpl contents;
+
+ /**
+ * Gets the ContentsImpl object to access its operations.
+ *
+ * @return the ContentsImpl object.
+ */
+ public ContentsImpl getContents() {
+ return this.contents;
+ }
+
+ /** The ServerCallsImpl object to access its operations. */
+ private final ServerCallsImpl serverCalls;
+
+ /**
+ * Gets the ServerCallsImpl object to access its operations.
+ *
+ * @return the ServerCallsImpl object.
+ */
+ public ServerCallsImpl getServerCalls() {
+ return this.serverCalls;
+ }
+
+ /**
+ * Initializes an instance of AzureCommunicationCallAutomationService client.
+ *
+ * @param endpoint The endpoint of the Azure Communication resource.
+ * @param apiVersion Api Version.
+ */
+ AzureCommunicationCallAutomationServiceImpl(String endpoint, String apiVersion) {
+ this(
+ new HttpPipelineBuilder()
+ .policies(new UserAgentPolicy(), new RetryPolicy(), new CookiePolicy())
+ .build(),
+ JacksonAdapter.createDefaultSerializerAdapter(),
+ endpoint,
+ apiVersion);
+ }
+
+ /**
+ * Initializes an instance of AzureCommunicationCallAutomationService client.
+ *
+ * @param httpPipeline The HTTP pipeline to send requests through.
+ * @param endpoint The endpoint of the Azure Communication resource.
+ * @param apiVersion Api Version.
+ */
+ AzureCommunicationCallAutomationServiceImpl(HttpPipeline httpPipeline, String endpoint, String apiVersion) {
+ this(httpPipeline, JacksonAdapter.createDefaultSerializerAdapter(), endpoint, apiVersion);
+ }
+
+ /**
+ * Initializes an instance of AzureCommunicationCallAutomationService client.
+ *
+ * @param httpPipeline The HTTP pipeline to send requests through.
+ * @param serializerAdapter The serializer to serialize an object into a string.
+ * @param endpoint The endpoint of the Azure Communication resource.
+ * @param apiVersion Api Version.
+ */
+ AzureCommunicationCallAutomationServiceImpl(
+ HttpPipeline httpPipeline, SerializerAdapter serializerAdapter, String endpoint, String apiVersion) {
+ this.httpPipeline = httpPipeline;
+ this.serializerAdapter = serializerAdapter;
+ this.endpoint = endpoint;
+ this.apiVersion = apiVersion;
+ this.serverCallings = new ServerCallingsImpl(this);
+ this.callConnections = new CallConnectionsImpl(this);
+ this.contents = new ContentsImpl(this);
+ this.serverCalls = new ServerCallsImpl(this);
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImplBuilder.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImplBuilder.java
new file mode 100644
index 0000000000000..9797d8fdb9a60
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/AzureCommunicationCallAutomationServiceImplBuilder.java
@@ -0,0 +1,230 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+// Code generated by Microsoft (R) AutoRest Code Generator.
+
+package com.azure.communication.callautomation.implementation;
+
+import com.azure.core.annotation.ServiceClientBuilder;
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.HttpPipelineBuilder;
+import com.azure.core.http.policy.CookiePolicy;
+import com.azure.core.http.policy.HttpLogOptions;
+import com.azure.core.http.policy.HttpLoggingPolicy;
+import com.azure.core.http.policy.HttpPipelinePolicy;
+import com.azure.core.http.policy.HttpPolicyProviders;
+import com.azure.core.http.policy.RetryPolicy;
+import com.azure.core.http.policy.UserAgentPolicy;
+import com.azure.core.util.Configuration;
+import com.azure.core.util.serializer.JacksonAdapter;
+import com.azure.core.util.serializer.SerializerAdapter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** A builder for creating a new instance of the AzureCommunicationCallAutomationService type. */
+@ServiceClientBuilder(serviceClients = {AzureCommunicationCallAutomationServiceImpl.class})
+public final class AzureCommunicationCallAutomationServiceImplBuilder {
+ private static final String SDK_NAME = "name";
+
+ private static final String SDK_VERSION = "version";
+
+ private final Map properties = new HashMap<>();
+
+ /** Create an instance of the AzureCommunicationCallAutomationServiceImplBuilder. */
+ public AzureCommunicationCallAutomationServiceImplBuilder() {
+ this.pipelinePolicies = new ArrayList<>();
+ }
+
+ /*
+ * The endpoint of the Azure Communication resource.
+ */
+ private String endpoint;
+
+ /**
+ * Sets The endpoint of the Azure Communication resource.
+ *
+ * @param endpoint the endpoint value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder endpoint(String endpoint) {
+ this.endpoint = endpoint;
+ return this;
+ }
+
+ /*
+ * Api Version
+ */
+ private String apiVersion;
+
+ /**
+ * Sets Api Version.
+ *
+ * @param apiVersion the apiVersion value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder apiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ return this;
+ }
+
+ /*
+ * The HTTP pipeline to send requests through
+ */
+ private HttpPipeline pipeline;
+
+ /**
+ * Sets The HTTP pipeline to send requests through.
+ *
+ * @param pipeline the pipeline value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder pipeline(HttpPipeline pipeline) {
+ this.pipeline = pipeline;
+ return this;
+ }
+
+ /*
+ * The serializer to serialize an object into a string
+ */
+ private SerializerAdapter serializerAdapter;
+
+ /**
+ * Sets The serializer to serialize an object into a string.
+ *
+ * @param serializerAdapter the serializerAdapter value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder serializerAdapter(SerializerAdapter serializerAdapter) {
+ this.serializerAdapter = serializerAdapter;
+ return this;
+ }
+
+ /*
+ * The HTTP client used to send the request.
+ */
+ private HttpClient httpClient;
+
+ /**
+ * Sets The HTTP client used to send the request.
+ *
+ * @param httpClient the httpClient value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder httpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ return this;
+ }
+
+ /*
+ * The configuration store that is used during construction of the service
+ * client.
+ */
+ private Configuration configuration;
+
+ /**
+ * Sets The configuration store that is used during construction of the service client.
+ *
+ * @param configuration the configuration value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder configuration(Configuration configuration) {
+ this.configuration = configuration;
+ return this;
+ }
+
+ /*
+ * The logging configuration for HTTP requests and responses.
+ */
+ private HttpLogOptions httpLogOptions;
+
+ /**
+ * Sets The logging configuration for HTTP requests and responses.
+ *
+ * @param httpLogOptions the httpLogOptions value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder httpLogOptions(HttpLogOptions httpLogOptions) {
+ this.httpLogOptions = httpLogOptions;
+ return this;
+ }
+
+ /*
+ * The retry policy that will attempt to retry failed requests, if
+ * applicable.
+ */
+ private RetryPolicy retryPolicy;
+
+ /**
+ * Sets The retry policy that will attempt to retry failed requests, if applicable.
+ *
+ * @param retryPolicy the retryPolicy value.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder retryPolicy(RetryPolicy retryPolicy) {
+ this.retryPolicy = retryPolicy;
+ return this;
+ }
+
+ /*
+ * The list of Http pipeline policies to add.
+ */
+ private final List pipelinePolicies;
+
+ /**
+ * Adds a custom Http pipeline policy.
+ *
+ * @param customPolicy The custom Http pipeline policy to add.
+ * @return the AzureCommunicationCallAutomationServiceImplBuilder.
+ */
+ public AzureCommunicationCallAutomationServiceImplBuilder addPolicy(HttpPipelinePolicy customPolicy) {
+ pipelinePolicies.add(customPolicy);
+ return this;
+ }
+
+ /**
+ * Builds an instance of AzureCommunicationCallAutomationServiceImpl with the provided parameters.
+ *
+ * @return an instance of AzureCommunicationCallAutomationServiceImpl.
+ */
+ public AzureCommunicationCallAutomationServiceImpl buildClient() {
+ if (apiVersion == null) {
+ this.apiVersion = "2022-04-07-preview";
+ }
+ if (pipeline == null) {
+ this.pipeline = createHttpPipeline();
+ }
+ if (serializerAdapter == null) {
+ this.serializerAdapter = JacksonAdapter.createDefaultSerializerAdapter();
+ }
+ AzureCommunicationCallAutomationServiceImpl client =
+ new AzureCommunicationCallAutomationServiceImpl(pipeline, serializerAdapter, endpoint, apiVersion);
+ return client;
+ }
+
+ private HttpPipeline createHttpPipeline() {
+ Configuration buildConfiguration =
+ (configuration == null) ? Configuration.getGlobalConfiguration() : configuration;
+ if (httpLogOptions == null) {
+ httpLogOptions = new HttpLogOptions();
+ }
+ List policies = new ArrayList<>();
+ String clientName = properties.getOrDefault(SDK_NAME, "UnknownName");
+ String clientVersion = properties.getOrDefault(SDK_VERSION, "UnknownVersion");
+ policies.add(
+ new UserAgentPolicy(httpLogOptions.getApplicationId(), clientName, clientVersion, buildConfiguration));
+ HttpPolicyProviders.addBeforeRetryPolicies(policies);
+ policies.add(retryPolicy == null ? new RetryPolicy() : retryPolicy);
+ policies.add(new CookiePolicy());
+ policies.addAll(this.pipelinePolicies);
+ HttpPolicyProviders.addAfterRetryPolicies(policies);
+ policies.add(new HttpLoggingPolicy(httpLogOptions));
+ HttpPipeline httpPipeline =
+ new HttpPipelineBuilder()
+ .policies(policies.toArray(new HttpPipelinePolicy[0]))
+ .httpClient(httpClient)
+ .build();
+ return httpPipeline;
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CallConnectionsImpl.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CallConnectionsImpl.java
new file mode 100644
index 0000000000000..8b624be45747c
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CallConnectionsImpl.java
@@ -0,0 +1,1080 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+// Code generated by Microsoft (R) AutoRest Code Generator.
+
+package com.azure.communication.callautomation.implementation;
+
+import com.azure.communication.callautomation.implementation.models.AcsCallParticipantInternal;
+import com.azure.communication.callautomation.implementation.models.AddParticipantsRequestInternal;
+import com.azure.communication.callautomation.implementation.models.AddParticipantsResponseInternal;
+import com.azure.communication.callautomation.implementation.models.CallConnectionPropertiesInternal;
+import com.azure.communication.callautomation.implementation.models.GetParticipantsResponseInternal;
+import com.azure.communication.callautomation.implementation.models.RemoveParticipantsRequestInternal;
+import com.azure.communication.callautomation.implementation.models.RemoveParticipantsResponseInternal;
+import com.azure.communication.callautomation.implementation.models.TransferCallResponseInternal;
+import com.azure.communication.callautomation.implementation.models.TransferToParticipantRequestInternal;
+import com.azure.core.annotation.BodyParam;
+import com.azure.core.annotation.Delete;
+import com.azure.core.annotation.ExpectedResponses;
+import com.azure.core.annotation.Get;
+import com.azure.core.annotation.HeaderParam;
+import com.azure.core.annotation.Host;
+import com.azure.core.annotation.HostParam;
+import com.azure.core.annotation.PathParam;
+import com.azure.core.annotation.Post;
+import com.azure.core.annotation.QueryParam;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceInterface;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.annotation.UnexpectedResponseExceptionType;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.RestProxy;
+import com.azure.core.util.Context;
+import com.azure.core.util.FluxUtil;
+import reactor.core.publisher.Mono;
+
+/** An instance of this class provides access to all the operations defined in CallConnections. */
+public final class CallConnectionsImpl {
+ /** The proxy service used to perform REST calls. */
+ private final CallConnectionsService service;
+
+ /** The service client containing this operation class. */
+ private final AzureCommunicationCallAutomationServiceImpl client;
+
+ /**
+ * Initializes an instance of CallConnectionsImpl.
+ *
+ * @param client the instance of the service client containing this operation class.
+ */
+ CallConnectionsImpl(AzureCommunicationCallAutomationServiceImpl client) {
+ this.service =
+ RestProxy.create(CallConnectionsService.class, client.getHttpPipeline(), client.getSerializerAdapter());
+ this.client = client;
+ }
+
+ /**
+ * The interface defining all the services for AzureCommunicationCallAutomationServiceCallConnections to be used by
+ * the proxy service to perform REST calls.
+ */
+ @Host("{endpoint}")
+ @ServiceInterface(name = "AzureCommunicationCa")
+ public interface CallConnectionsService {
+ @Get("/calling/callConnections/{callConnectionId}")
+ @ExpectedResponses({200})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> getCall(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @HeaderParam("Accept") String accept,
+ Context context);
+
+ @Delete("/calling/callConnections/{callConnectionId}")
+ @ExpectedResponses({204})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> hangupCall(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}:terminate")
+ @ExpectedResponses({204})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> terminateCall(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}:transferToParticipant")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> transferToParticipant(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") TransferToParticipantRequestInternal transferToParticipantRequest,
+ @HeaderParam("Accept") String accept,
+ Context context);
+
+ @Get("/calling/callConnections/{callConnectionId}/participants")
+ @ExpectedResponses({200})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> getParticipants(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @HeaderParam("Accept") String accept,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}/participants:add")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> addParticipant(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") AddParticipantsRequestInternal addParticipantsRequest,
+ @HeaderParam("Accept") String accept,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}/participants:remove")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> removeParticipants(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") RemoveParticipantsRequestInternal removeParticipantsRequest,
+ @HeaderParam("Accept") String accept,
+ Context context);
+
+ @Get("/calling/callConnections/{callConnectionId}/participants/{participantMri}")
+ @ExpectedResponses({200})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> getParticipant(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @PathParam("participantMri") String participantMri,
+ @QueryParam("api-version") String apiVersion,
+ @HeaderParam("Accept") String accept,
+ Context context);
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getCallWithResponseAsync(String callConnectionId) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.getCall(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ accept,
+ context));
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getCallWithResponseAsync(
+ String callConnectionId, Context context) {
+ final String accept = "application/json";
+ return service.getCall(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), accept, context);
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getCallAsync(String callConnectionId) {
+ return getCallWithResponseAsync(callConnectionId)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getCallAsync(String callConnectionId, Context context) {
+ return getCallWithResponseAsync(callConnectionId, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public CallConnectionPropertiesInternal getCall(String callConnectionId) {
+ return getCallAsync(callConnectionId).block();
+ }
+
+ /**
+ * Get call connection.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return call connection.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getCallWithResponse(String callConnectionId, Context context) {
+ return getCallWithResponseAsync(callConnectionId, context).block();
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> hangupCallWithResponseAsync(String callConnectionId) {
+ return FluxUtil.withContext(
+ context ->
+ service.hangupCall(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context));
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> hangupCallWithResponseAsync(String callConnectionId, Context context) {
+ return service.hangupCall(this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context);
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono hangupCallAsync(String callConnectionId) {
+ return hangupCallWithResponseAsync(callConnectionId).flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono hangupCallAsync(String callConnectionId, Context context) {
+ return hangupCallWithResponseAsync(callConnectionId, context).flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void hangupCall(String callConnectionId) {
+ hangupCallAsync(callConnectionId).block();
+ }
+
+ /**
+ * Hangup the call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response hangupCallWithResponse(String callConnectionId, Context context) {
+ return hangupCallWithResponseAsync(callConnectionId, context).block();
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> terminateCallWithResponseAsync(String callConnectionId) {
+ return FluxUtil.withContext(
+ context ->
+ service.terminateCall(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context));
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> terminateCallWithResponseAsync(String callConnectionId, Context context) {
+ return service.terminateCall(this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context);
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono terminateCallAsync(String callConnectionId) {
+ return terminateCallWithResponseAsync(callConnectionId).flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono terminateCallAsync(String callConnectionId, Context context) {
+ return terminateCallWithResponseAsync(callConnectionId, context).flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void terminateCall(String callConnectionId) {
+ terminateCallAsync(callConnectionId).block();
+ }
+
+ /**
+ * Terminate a call using CallConnectionId.
+ *
+ * @param callConnectionId The terminate call request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response terminateCallWithResponse(String callConnectionId, Context context) {
+ return terminateCallWithResponseAsync(callConnectionId, context).block();
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> transferToParticipantWithResponseAsync(
+ String callConnectionId, TransferToParticipantRequestInternal transferToParticipantRequest) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.transferToParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ transferToParticipantRequest,
+ accept,
+ context));
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> transferToParticipantWithResponseAsync(
+ String callConnectionId,
+ TransferToParticipantRequestInternal transferToParticipantRequest,
+ Context context) {
+ final String accept = "application/json";
+ return service.transferToParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ transferToParticipantRequest,
+ accept,
+ context);
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono transferToParticipantAsync(
+ String callConnectionId, TransferToParticipantRequestInternal transferToParticipantRequest) {
+ return transferToParticipantWithResponseAsync(callConnectionId, transferToParticipantRequest)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono transferToParticipantAsync(
+ String callConnectionId,
+ TransferToParticipantRequestInternal transferToParticipantRequest,
+ Context context) {
+ return transferToParticipantWithResponseAsync(callConnectionId, transferToParticipantRequest, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public TransferCallResponseInternal transferToParticipant(
+ String callConnectionId, TransferToParticipantRequestInternal transferToParticipantRequest) {
+ return transferToParticipantAsync(callConnectionId, transferToParticipantRequest).block();
+ }
+
+ /**
+ * Transfer the call to a participant.
+ *
+ * @param callConnectionId The call connection id.
+ * @param transferToParticipantRequest The transfer to participant request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response transferToParticipantWithResponse(
+ String callConnectionId,
+ TransferToParticipantRequestInternal transferToParticipantRequest,
+ Context context) {
+ return transferToParticipantWithResponseAsync(callConnectionId, transferToParticipantRequest, context).block();
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getParticipantsWithResponseAsync(String callConnectionId) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.getParticipants(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ accept,
+ context));
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getParticipantsWithResponseAsync(
+ String callConnectionId, Context context) {
+ final String accept = "application/json";
+ return service.getParticipants(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), accept, context);
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getParticipantsAsync(String callConnectionId) {
+ return getParticipantsWithResponseAsync(callConnectionId)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getParticipantsAsync(String callConnectionId, Context context) {
+ return getParticipantsWithResponseAsync(callConnectionId, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public GetParticipantsResponseInternal getParticipants(String callConnectionId) {
+ return getParticipantsAsync(callConnectionId).block();
+ }
+
+ /**
+ * Get participants from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participants from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getParticipantsWithResponse(
+ String callConnectionId, Context context) {
+ return getParticipantsWithResponseAsync(callConnectionId, context).block();
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> addParticipantWithResponseAsync(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.addParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ addParticipantsRequest,
+ accept,
+ context));
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> addParticipantWithResponseAsync(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest, Context context) {
+ final String accept = "application/json";
+ return service.addParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ addParticipantsRequest,
+ accept,
+ context);
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono addParticipantAsync(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest) {
+ return addParticipantWithResponseAsync(callConnectionId, addParticipantsRequest)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono addParticipantAsync(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest, Context context) {
+ return addParticipantWithResponseAsync(callConnectionId, addParticipantsRequest, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public AddParticipantsResponseInternal addParticipant(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest) {
+ return addParticipantAsync(callConnectionId, addParticipantsRequest).block();
+ }
+
+ /**
+ * Add participants to the call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param addParticipantsRequest The add participants request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response addParticipantWithResponse(
+ String callConnectionId, AddParticipantsRequestInternal addParticipantsRequest, Context context) {
+ return addParticipantWithResponseAsync(callConnectionId, addParticipantsRequest, context).block();
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> removeParticipantsWithResponseAsync(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.removeParticipants(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ removeParticipantsRequest,
+ accept,
+ context));
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> removeParticipantsWithResponseAsync(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest, Context context) {
+ final String accept = "application/json";
+ return service.removeParticipants(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ removeParticipantsRequest,
+ accept,
+ context);
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono removeParticipantsAsync(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest) {
+ return removeParticipantsWithResponseAsync(callConnectionId, removeParticipantsRequest)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono removeParticipantsAsync(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest, Context context) {
+ return removeParticipantsWithResponseAsync(callConnectionId, removeParticipantsRequest, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public RemoveParticipantsResponseInternal removeParticipants(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest) {
+ return removeParticipantsAsync(callConnectionId, removeParticipantsRequest).block();
+ }
+
+ /**
+ * Remove participant from the call using identifier.
+ *
+ * @param callConnectionId The call connection id.
+ * @param removeParticipantsRequest The participants to be removed from the call.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response removeParticipantsWithResponse(
+ String callConnectionId, RemoveParticipantsRequestInternal removeParticipantsRequest, Context context) {
+ return removeParticipantsWithResponseAsync(callConnectionId, removeParticipantsRequest, context).block();
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getParticipantWithResponseAsync(
+ String callConnectionId, String participantMri) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.getParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ participantMri,
+ this.client.getApiVersion(),
+ accept,
+ context));
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> getParticipantWithResponseAsync(
+ String callConnectionId, String participantMri, Context context) {
+ final String accept = "application/json";
+ return service.getParticipant(
+ this.client.getEndpoint(),
+ callConnectionId,
+ participantMri,
+ this.client.getApiVersion(),
+ accept,
+ context);
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getParticipantAsync(String callConnectionId, String participantMri) {
+ return getParticipantWithResponseAsync(callConnectionId, participantMri)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono getParticipantAsync(
+ String callConnectionId, String participantMri, Context context) {
+ return getParticipantWithResponseAsync(callConnectionId, participantMri, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public AcsCallParticipantInternal getParticipant(String callConnectionId, String participantMri) {
+ return getParticipantAsync(callConnectionId, participantMri).block();
+ }
+
+ /**
+ * Get participant from a call.
+ *
+ * @param callConnectionId The call connection Id.
+ * @param participantMri MRI of the participants to retrieve.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return participant from a call.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response getParticipantWithResponse(
+ String callConnectionId, String participantMri, Context context) {
+ return getParticipantWithResponseAsync(callConnectionId, participantMri, context).block();
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/Constants.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/Constants.java
new file mode 100644
index 0000000000000..e2568110b0d93
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/Constants.java
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.communication.callautomation.implementation;
+
+/***
+ * Constants to be used by CallingServer.
+ */
+public final class Constants {
+ public static final int KB = 1024;
+ public static final int MB = KB * 1024;
+
+ /***
+ * Content downloader constants
+ */
+ public static class ContentDownloader {
+ public static final int DEFAULT_CONCURRENT_TRANSFERS_COUNT = 5;
+ public static final int DEFAULT_BUFFER_SIZE = 4 * MB;
+ public static final int DEFAULT_INITIAL_DOWNLOAD_RANGE_SIZE = 256 * MB;
+ public static final int MAX_RETRIES = 4;
+ }
+
+ /***
+ * HTTP Header Names
+ */
+ public static class HeaderNames {
+ public static final String RANGE = "Range";
+ public static final String CONTENT_RANGE = "Content-Range";
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/ContentsImpl.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/ContentsImpl.java
new file mode 100644
index 0000000000000..0dcc091b2d744
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/ContentsImpl.java
@@ -0,0 +1,509 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+// Code generated by Microsoft (R) AutoRest Code Generator.
+
+package com.azure.communication.callautomation.implementation;
+
+import com.azure.communication.callautomation.implementation.models.PlayRequest;
+import com.azure.communication.callautomation.implementation.models.RecognizeRequest;
+import com.azure.communication.callautomation.implementation.models.RecordingStateResponseInternal;
+import com.azure.communication.callautomation.implementation.models.StartCallRecordingRequestInternal;
+import com.azure.core.annotation.BodyParam;
+import com.azure.core.annotation.ExpectedResponses;
+import com.azure.core.annotation.HeaderParam;
+import com.azure.core.annotation.Host;
+import com.azure.core.annotation.HostParam;
+import com.azure.core.annotation.PathParam;
+import com.azure.core.annotation.Post;
+import com.azure.core.annotation.QueryParam;
+import com.azure.core.annotation.ReturnType;
+import com.azure.core.annotation.ServiceInterface;
+import com.azure.core.annotation.ServiceMethod;
+import com.azure.core.annotation.UnexpectedResponseExceptionType;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.RestProxy;
+import com.azure.core.util.Context;
+import com.azure.core.util.FluxUtil;
+import reactor.core.publisher.Mono;
+
+/** An instance of this class provides access to all the operations defined in Contents. */
+public final class ContentsImpl {
+ /** The proxy service used to perform REST calls. */
+ private final ContentsService service;
+
+ /** The service client containing this operation class. */
+ private final AzureCommunicationCallAutomationServiceImpl client;
+
+ /**
+ * Initializes an instance of ContentsImpl.
+ *
+ * @param client the instance of the service client containing this operation class.
+ */
+ ContentsImpl(AzureCommunicationCallAutomationServiceImpl client) {
+ this.service = RestProxy.create(ContentsService.class, client.getHttpPipeline(), client.getSerializerAdapter());
+ this.client = client;
+ }
+
+ /**
+ * The interface defining all the services for AzureCommunicationCallAutomationServiceContents to be used by the
+ * proxy service to perform REST calls.
+ */
+ @Host("{endpoint}")
+ @ServiceInterface(name = "AzureCommunicationCa")
+ public interface ContentsService {
+ @Post("/calling/callConnections/{callConnectionId}:play")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> play(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") PlayRequest playRequest,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}:cancelAllMediaOperations")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> cancelAllMediaOperations(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ Context context);
+
+ @Post("/calling/callConnections/{callConnectionId}:recognize")
+ @ExpectedResponses({202})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> recognize(
+ @HostParam("endpoint") String endpoint,
+ @PathParam("callConnectionId") String callConnectionId,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") RecognizeRequest recognizeRequest,
+ Context context);
+
+ @Post("/calling/recordings")
+ @ExpectedResponses({200})
+ @UnexpectedResponseExceptionType(HttpResponseException.class)
+ Mono> recording(
+ @HostParam("endpoint") String endpoint,
+ @QueryParam("api-version") String apiVersion,
+ @BodyParam("application/json") StartCallRecordingRequestInternal startCallRecording,
+ @HeaderParam("Accept") String accept,
+ Context context);
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> playWithResponseAsync(String callConnectionId, PlayRequest playRequest) {
+ return FluxUtil.withContext(
+ context ->
+ service.play(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ playRequest,
+ context));
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> playWithResponseAsync(
+ String callConnectionId, PlayRequest playRequest, Context context) {
+ return service.play(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), playRequest, context);
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono playAsync(String callConnectionId, PlayRequest playRequest) {
+ return playWithResponseAsync(callConnectionId, playRequest).flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono playAsync(String callConnectionId, PlayRequest playRequest, Context context) {
+ return playWithResponseAsync(callConnectionId, playRequest, context)
+ .flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void play(String callConnectionId, PlayRequest playRequest) {
+ playAsync(callConnectionId, playRequest).block();
+ }
+
+ /**
+ * Plays audio to participants in the call.
+ *
+ * @param callConnectionId The callConnectionId parameter.
+ * @param playRequest The playRequest parameter.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response playWithResponse(String callConnectionId, PlayRequest playRequest, Context context) {
+ return playWithResponseAsync(callConnectionId, playRequest, context).block();
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> cancelAllMediaOperationsWithResponseAsync(String callConnectionId) {
+ return FluxUtil.withContext(
+ context ->
+ service.cancelAllMediaOperations(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context));
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> cancelAllMediaOperationsWithResponseAsync(String callConnectionId, Context context) {
+ return service.cancelAllMediaOperations(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), context);
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono cancelAllMediaOperationsAsync(String callConnectionId) {
+ return cancelAllMediaOperationsWithResponseAsync(callConnectionId)
+ .flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono cancelAllMediaOperationsAsync(String callConnectionId, Context context) {
+ return cancelAllMediaOperationsWithResponseAsync(callConnectionId, context)
+ .flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void cancelAllMediaOperations(String callConnectionId) {
+ cancelAllMediaOperationsAsync(callConnectionId).block();
+ }
+
+ /**
+ * Cancel all media operations in a call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response cancelAllMediaOperationsWithResponse(String callConnectionId, Context context) {
+ return cancelAllMediaOperationsWithResponseAsync(callConnectionId, context).block();
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> recognizeWithResponseAsync(String callConnectionId, RecognizeRequest recognizeRequest) {
+ return FluxUtil.withContext(
+ context ->
+ service.recognize(
+ this.client.getEndpoint(),
+ callConnectionId,
+ this.client.getApiVersion(),
+ recognizeRequest,
+ context));
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> recognizeWithResponseAsync(
+ String callConnectionId, RecognizeRequest recognizeRequest, Context context) {
+ return service.recognize(
+ this.client.getEndpoint(), callConnectionId, this.client.getApiVersion(), recognizeRequest, context);
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono recognizeAsync(String callConnectionId, RecognizeRequest recognizeRequest) {
+ return recognizeWithResponseAsync(callConnectionId, recognizeRequest)
+ .flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the completion.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono recognizeAsync(String callConnectionId, RecognizeRequest recognizeRequest, Context context) {
+ return recognizeWithResponseAsync(callConnectionId, recognizeRequest, context)
+ .flatMap((Response res) -> Mono.empty());
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public void recognize(String callConnectionId, RecognizeRequest recognizeRequest) {
+ recognizeAsync(callConnectionId, recognizeRequest).block();
+ }
+
+ /**
+ * Recognize media from call.
+ *
+ * @param callConnectionId The call connection id.
+ * @param recognizeRequest The media recognize request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response recognizeWithResponse(
+ String callConnectionId, RecognizeRequest recognizeRequest, Context context) {
+ return recognizeWithResponseAsync(callConnectionId, recognizeRequest, context).block();
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> recordingWithResponseAsync(
+ StartCallRecordingRequestInternal startCallRecording) {
+ final String accept = "application/json";
+ return FluxUtil.withContext(
+ context ->
+ service.recording(
+ this.client.getEndpoint(),
+ this.client.getApiVersion(),
+ startCallRecording,
+ accept,
+ context));
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono> recordingWithResponseAsync(
+ StartCallRecordingRequestInternal startCallRecording, Context context) {
+ final String accept = "application/json";
+ return service.recording(
+ this.client.getEndpoint(), this.client.getApiVersion(), startCallRecording, accept, context);
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono recordingAsync(StartCallRecordingRequestInternal startCallRecording) {
+ return recordingWithResponseAsync(startCallRecording)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Mono recordingAsync(
+ StartCallRecordingRequestInternal startCallRecording, Context context) {
+ return recordingWithResponseAsync(startCallRecording, context)
+ .flatMap(
+ (Response res) -> {
+ if (res.getValue() != null) {
+ return Mono.just(res.getValue());
+ } else {
+ return Mono.empty();
+ }
+ });
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public RecordingStateResponseInternal recording(StartCallRecordingRequestInternal startCallRecording) {
+ return recordingAsync(startCallRecording).block();
+ }
+
+ /**
+ * Start recording the call.
+ *
+ * @param startCallRecording The request body of start call recording request.
+ * @param context The context to associate with this operation.
+ * @throws IllegalArgumentException thrown if parameters fail the validation.
+ * @throws HttpResponseException thrown if the request is rejected by server.
+ * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
+ * @return the response.
+ */
+ @ServiceMethod(returns = ReturnType.SINGLE)
+ public Response recordingWithResponse(
+ StartCallRecordingRequestInternal startCallRecording, Context context) {
+ return recordingWithResponseAsync(startCallRecording, context).block();
+ }
+}
diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CustomHmacAuthenticationPolicy.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CustomHmacAuthenticationPolicy.java
new file mode 100644
index 0000000000000..196364be214ed
--- /dev/null
+++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CustomHmacAuthenticationPolicy.java
@@ -0,0 +1,164 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.communication.callautomation.implementation;
+
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import com.azure.core.credential.AzureKeyCredential;
+import com.azure.core.http.HttpPipelineCallContext;
+import com.azure.core.http.HttpPipelineNextPolicy;
+import com.azure.core.http.HttpResponse;
+import com.azure.core.http.policy.HttpPipelinePolicy;
+
+import com.azure.core.util.logging.ClientLogger;
+import reactor.core.Exceptions;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * HttpPipelinePolicy to append CommunicationClient required headers
+ */
+public final class CustomHmacAuthenticationPolicy implements HttpPipelinePolicy {
+ private static final String X_MS_DATE_HEADER = "x-ms-date";
+ private static final String X_MS_STRING_TO_SIGN_HEADER = "x-ms-hmac-string-to-sign-base64";
+ private static final String HOST_HEADER = "host";
+ private static final String CONTENT_HASH_HEADER = "x-ms-content-sha256";
+ // Order of the headers are important here for generating correct signature
+ private static final String[] SIGNED_HEADERS = new String[]{X_MS_DATE_HEADER, HOST_HEADER, CONTENT_HASH_HEADER};
+
+ private static final String AUTHORIZATIONHEADERNAME = "Authorization";
+ private static final String HMACSHA256FORMAT = "HMAC-SHA256 SignedHeaders=%s&Signature=%s";
+
+ // Previously DateTimeFormatter.RFC_1123_DATE_TIME was being used. There
+ // was an issue with the day of month part. RFC_1123_DATE_TIME does not
+ // append a leading '0' on days that are less than 10. It is important
+ // that the locale remain US. In other locals the values that are generated
+ // for the day and month strings may be different. (e.g. Canada day strings
+ // have a '.' at the end)
+ static final DateTimeFormatter HMAC_DATETIMEFORMATTER_PATTERN =
+ DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
+
+ private final AzureKeyCredential credential;
+ private final String acsResource;
+ private final ClientLogger logger = new ClientLogger(CustomHmacAuthenticationPolicy.class);
+
+ /**
+ * Created with a non-null client credential
+ * @param clientCredential client credential with valid access key
+ * @param acsResource the acs resource endpoint
+ */
+ public CustomHmacAuthenticationPolicy(AzureKeyCredential clientCredential, String acsResource) {
+ Objects.requireNonNull(clientCredential, "'clientCredential' cannot be a null value.");
+ this.credential = clientCredential;
+ this.acsResource = acsResource;
+ }
+
+ @Override
+ public Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
+ final Flux contents = context.getHttpRequest().getBody() == null
+ ? Flux.just(ByteBuffer.allocate(0))
+ : context.getHttpRequest().getBody();
+
+ if ("http".equals(context.getHttpRequest().getUrl().getProtocol())) {
+ return Mono.error(
+ new RuntimeException("AzureKeyCredential requires a URL using the HTTPS protocol scheme"));
+ }
+
+ try {
+ URL hostnameToSignWith = context.getData("hmacSignatureURL")
+ .filter(alternativeUrl -> alternativeUrl instanceof URL)
+ .map(alternativeUrl -> (URL) alternativeUrl)
+ .orElse(context.getHttpRequest().getUrl());
+
+ return appendAuthorizationHeaders(
+ hostnameToSignWith,
+ context.getHttpRequest().getHttpMethod().toString(),
+ contents)
+ .flatMap(headers -> {
+ headers.entrySet().forEach(
+ header -> context.getHttpRequest().setHeader(header.getKey(), header.getValue()));
+
+ return next.process();
+ });
+ } catch (RuntimeException r) {
+ return Mono.error(r);
+ }
+ }
+
+ private Mono