From 30fe001fb288ceed4e12fb53955b37b3e0c15afa Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Fri, 16 Aug 2019 15:20:46 -0500 Subject: [PATCH 01/26] Added AdalAuthenticator and utilized in MicrosoftAppCredentials. --- .../bot/builder/BotFrameworkAdapter.java | 1558 ++++++++--------- .../bot/connector/ExecutorFactory.java | 35 + .../authentication/AdalAuthenticator.java | 29 + .../AuthenticationConstants.java | 118 +- .../MicrosoftAppCredentials.java | 130 +- .../MicrosoftAppCredentialsInterceptor.java | 9 +- .../connector/authentication/OAuthClient.java | 2 +- .../authentication/OAuthConfiguration.java | 54 + .../bot/connector/BotAuthenticatorTest.java | 6 +- .../connector/JwtTokenValidationTests.java | 23 +- .../bot/connector/OAuthTestBase.java | 2 +- 11 files changed, 1102 insertions(+), 864 deletions(-) create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index 2c850e05b..79e576f6b 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -1,779 +1,779 @@ -package com.microsoft.bot.builder; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import com.microsoft.bot.connector.ConnectorClient; -import com.microsoft.bot.connector.Conversations; -import com.microsoft.bot.connector.authentication.*; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.bot.connector.implementation.ConversationsImpl; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.*; -import com.microsoft.rest.retry.RetryStrategy; -import org.apache.commons.lang3.StringUtils; -import sun.net.www.http.HttpClient; - -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import java.util.function.Function; - -import static java.util.concurrent.CompletableFuture.completedFuture; - -/** - * A bot adapter that can connect a bot to a service endpoint. - * The bot adapter encapsulates authentication processes and sends - * activities to and receives activities from the Bot Connector Service. When your - * bot receives an activity, the adapter creates a context object, passes it to your - * bot's application logic, and sends responses back to the user's channel. - *

Use {@link Use(Middleware)} to add {@link Middleware} objects - * to your adapter’s middleware collection. The adapter processes and directs - * incoming activities in through the bot middleware pipeline to your bot’s logic - * and then back out again. As each activity flows in and out of the bot, each piece - * of middleware can inspect or act upon the activity, both before and after the bot - * logic runs.

- *

- * {@linkalso TurnContext} - * {@linkalso Activity} - * {@linkalso Bot} - * {@linkalso Middleware} - */ -public class BotFrameworkAdapter extends BotAdapter { - private final CredentialProvider _credentialProvider; - - private final RetryStrategy connectorClientRetryStrategy; - private Map appCredentialMap = new HashMap(); - - private final String InvokeReponseKey = "BotFrameworkAdapter.InvokeResponse"; - private boolean isEmulatingOAuthCards = false; - - /** - * Initializes a new instance of the {@link BotFrameworkAdapter} class, - * using a credential provider. - * - * @param credentialProvider The credential provider. - * @param connectorClientRetryStrategy Retry strategy for retrying HTTP operations. - * @param httpClient The HTTP client. - * @param middleware The middleware to initially add to the adapter. - * @throws IllegalArgumentException {@code credentialProvider} is {@code null}. - * Use a {@link MiddlewareSet} object to add multiple middleware - * components in the conustructor. Use the {@link Use(Middleware)} method to - * add additional middleware to the adapter after construction. - */ - public BotFrameworkAdapter(CredentialProvider credentialProvider) { - this(credentialProvider, null, null, null); - } - - public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy) { - this(credentialProvider, connectorClientRetryStrategy, null, null); - } - - public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient) { - this(credentialProvider, connectorClientRetryStrategy, httpClient, null); - } - - public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient, Middleware middleware) { - if (credentialProvider == null) - throw new IllegalArgumentException("credentialProvider"); - _credentialProvider = credentialProvider; - //_httpClient = httpClient ?? new HttpClient(); - this.connectorClientRetryStrategy = connectorClientRetryStrategy; - - if (middleware != null) { - this.Use(middleware); - } - } - - /** - * Sends a proactive message from the bot to a conversation. - * - * @param botAppId The application ID of the bot. This is the appId returned by Portal registration, and is - * generally found in the "MicrosoftAppId" parameter in appSettings.json. - * @param reference A reference to the conversation to continue. - * @param callback The method to call for the resulting bot turn. - * @return A task that represents the work queued to execute. - * @throws IllegalArgumentException {@code botAppId}, {@code reference}, or - * {@code callback} is {@code null}. - * Call this method to proactively send a message to a conversation. - * Most channels require a user to initaiate a conversation with a bot - * before the bot can send activities to the user. - *

This method registers the following.services().for the turn. - * {@link ConnectorClient}, the channel connector client to use this turn. - *

- *

- * This overload differers from the Node implementation by requiring the BotId to be - * passed in. The .Net code allows multiple bots to be hosted in a single adapter which - * isn't something supported by Node. - *

- *

- * {@linkalso ProcessActivity(String, Activity, Func { TurnContext, Task })} - * {@linkalso BotAdapter.RunPipeline(TurnContext, Func { TurnContext, Task } } - */ - @Override - public void ContinueConversation(String botAppId, ConversationReference reference, Consumer callback) throws Exception { - if (StringUtils.isEmpty(botAppId)) - throw new IllegalArgumentException("botAppId"); - - if (reference == null) - throw new IllegalArgumentException("reference"); - - if (callback == null) - throw new IllegalArgumentException("callback"); - - try (TurnContextImpl context = new TurnContextImpl(this, new ConversationReferenceHelper(reference).GetPostToBotMessage())) { - // Hand craft Claims Identity. - HashMap claims = new HashMap(); - claims.put(AuthenticationConstants.AudienceClaim, botAppId); - claims.put(AuthenticationConstants.AppIdClaim, botAppId); - ClaimsIdentityImpl claimsIdentity = new ClaimsIdentityImpl("ExternalBearer", claims); - - context.getServices().Add("BotIdentity", claimsIdentity); - - ConnectorClient connectorClient = this.CreateConnectorClientAsync(reference.serviceUrl(), claimsIdentity).join(); - context.getServices().Add("ConnectorClient", connectorClient); - RunPipeline(context, callback); - } - return; - } - - /** - * Initializes a new instance of the {@link BotFrameworkAdapter} class, - * using an application ID and secret. - * - * @param appId The application ID of the bot. - * @param appPassword The application secret for the bot. - * @param connectorClientRetryStrategy Retry policy for retrying HTTP operations. - * @param httpClient The HTTP client. - * @param middleware The middleware to initially add to the adapter. - * Use a {@link MiddlewareSet} object to add multiple middleware - * components in the conustructor. Use the {@link Use(Middleware)} method to - * add additional middleware to the adapter after construction. - */ - public BotFrameworkAdapter(String appId, String appPassword) { - this(appId, appPassword, null, null, null); - } - - public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy) { - this(appId, appPassword, connectorClientRetryStrategy, null, null); - } - - public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient) { - this(appId, appPassword, connectorClientRetryStrategy, httpClient, null); - } - - public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient, Middleware middleware) { - this(new SimpleCredentialProvider(appId, appPassword), connectorClientRetryStrategy, httpClient, middleware); - } - - /** - * Adds middleware to the adapter's pipeline. - * - * @param middleware The middleware to add. - * @return The updated adapter object. - * Middleware is added to the adapter at initialization time. - * For each turn, the adapter calls middleware in the order in which you added it. - */ - - public BotFrameworkAdapter Use(Middleware middleware) { - super._middlewareSet.Use(middleware); - return this; - } - - /** - * Creates a turn context and runs the middleware pipeline for an incoming activity. - * - * @param authHeader The HTTP authentication header of the request. - * @param activity The incoming activity. - * @param callback The code to run at the end of the adapter's middleware - * pipeline. - * @return A task that represents the work queued to execute. If the activity type - * was 'Invoke' and the corresponding key (channelId + activityId) was found - * then an InvokeResponse is returned, otherwise null is returned. - * @throws IllegalArgumentException {@code activity} is {@code null}. - * @throws UnauthorizedAccessException authentication failed. - * Call this method to reactively send a message to a conversation. - *

This method registers the following.services().for the turn. - * {@link ConnectorClient}, the channel connector client to use this turn. - *

- *

- * {@linkalso ContinueConversation(String, ConversationReference, Func { TurnContext, Task })} - * {@linkalso BotAdapter.RunPipeline(TurnContext, Func { TurnContext, Task })} - */ - public CompletableFuture ProcessActivity(String authHeader, ActivityImpl activity, Function callback) throws Exception { - BotAssert.ActivityNotNull(activity); - - //ClaimsIdentity claimsIdentity = await(JwtTokenValidation.validateAuthHeader(activity, authHeader, _credentialProvider)); - - //return completedFuture(await(ProcessActivity(claimsIdentity, activity, callback))); - return completedFuture(null); - } - - public CompletableFuture ProcessActivity(ClaimsIdentity identity, ActivityImpl activity, Consumer callback) throws Exception { - BotAssert.ActivityNotNull(activity); - - try (TurnContextImpl context = new TurnContextImpl(this, activity)) { - context.getServices().Add("BotIdentity", identity); - - ConnectorClient connectorClient = this.CreateConnectorClientAsync(activity.serviceUrl(), identity).join(); - // TODO: Verify key that C# uses - context.getServices().Add("ConnectorClient", connectorClient); - - super.RunPipeline(context, callback); - - // Handle Invoke scenarios, which deviate from the request/response model in that - // the Bot will return a specific body and return code. - if (activity.type() == ActivityTypes.INVOKE) { - Activity invokeResponse = context.getServices().Get(InvokeReponseKey); - if (invokeResponse == null) { - // ToDo: Trace Here - throw new IllegalStateException("Bot failed to return a valid 'invokeResponse' activity."); - } else { - return completedFuture((InvokeResponse) invokeResponse.value()); - } - } - - // For all non-invoke scenarios, the HTTP layers above don't have to mess - // withthe Body and return codes. - return null; - } - } - - /** - * Sends activities to the conversation. - * - * @param context The context object for the turn. - * @param activities The activities to send. - * @return A task that represents the work queued to execute. - * If the activities are successfully sent, the task result contains - * an array of {@link ResourceResponse} objects containing the IDs that - * the receiving channel assigned to the activities. - * {@linkalso TurnContext.OnSendActivities(SendActivitiesHandler)} - */ - public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { - if (context == null) { - throw new IllegalArgumentException("context"); - } - - if (activities == null) { - throw new IllegalArgumentException("activities"); - } - - if (activities.length == 0) { - throw new IllegalArgumentException("Expecting one or more activities, but the array was empty."); - } - - ResourceResponse[] responses = new ResourceResponse[activities.length]; - - /* - * NOTE: we're using for here (vs. foreach) because we want to simultaneously index into the - * activities array to get the activity to process as well as use that index to assign - * the response to the responses array and this is the most cost effective way to do that. - */ - for (int index = 0; index < activities.length; index++) { - Activity activity = activities[index]; - ResourceResponse response = new ResourceResponse(); - - if (activity.type().toString().equals("delay")) { - // The Activity Schema doesn't have a delay type build in, so it's simulated - // here in the Bot. This matches the behavior in the Node connector. - int delayMs = (int) activity.value(); - Thread.sleep(delayMs); - //await(Task.Delay(delayMs)); - // No need to create a response. One will be created below. - } else if (activity.type().toString().equals("invokeResponse")) // Aligning name with Node - { - context.getServices().Add(InvokeReponseKey, activity); - // No need to create a response. One will be created below. - } else if (activity.type() == ActivityTypes.TRACE && !activity.channelId().equals("emulator")) { - // if it is a Trace activity we only send to the channel if it's the emulator. - } else if (!StringUtils.isEmpty(activity.replyToId())) { - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().replyToActivity(activity.conversation().id(), activity.id(), activity); - } else { - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().sendToConversation(activity.conversation().id(), activity); - } - - // If No response is set, then defult to a "simple" response. This can't really be done - // above, as there are cases where the ReplyTo/SendTo methods will also return null - // (See below) so the check has to happen here. - - // Note: In addition to the Invoke / Delay / Activity cases, this code also applies - // with Skype and Teams with regards to typing events. When sending a typing event in - // these channels they do not return a RequestResponse which causes the bot to blow up. - // https://github.com/Microsoft/botbuilder-dotnet/issues/460 - // bug report : https://github.com/Microsoft/botbuilder-dotnet/issues/465 - if (response == null) { - response = new ResourceResponse().withId((activity.id() == null) ? "" : activity.id()); - } - - responses[index] = response; - } - - return responses; - } - - /** - * Replaces an existing activity in the conversation. - * - * @param context The context object for the turn. - * @param activity New replacement activity. - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

- * {@linkalso TurnContext.OnUpdateActivity(UpdateActivityHandler)} - */ - @Override - public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - // TODO String conversationId, String activityId, Activity activity) - return connectorClient.conversations().updateActivity(activity.conversation().id(), activity.id(), activity); - } - - /** - * Deletes an existing activity in the conversation. - * - * @param context The context object for the turn. - * @param reference Conversation reference for the activity to delete. - * @return A task that represents the work queued to execute. - * The {@link ConversationReference.ActivityId} of the conversation - * reference identifies the activity to delete. - * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} - */ - public void DeleteActivity(TurnContext context, ConversationReference reference) { - ConnectorClientImpl connectorClient = context.getServices().Get("ConnectorClient"); - try { - connectorClient.conversations().deleteConversationMemberFuture(reference.conversation().id(), reference.activityId()).join(); - } catch (ExecutionException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); - } catch (InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); - } - return; - } - - /** - * Deletes a member from the current conversation - * - * @param context The context object for the turn. - * @param memberId ID of the member to delete from the conversation - * @return - */ - public void DeleteConversationMember(TurnContextImpl context, String memberId) { - if (context.getActivity().conversation() == null) - throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation"); - - if (StringUtils.isEmpty(context.getActivity().conversation().id())) - throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation.id"); - - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - - String conversationId = context.getActivity().conversation().id(); - - // TODO: - //await (connectorClient.conversations().DeleteConversationMemberAsync(conversationId, memberId)); - return; - } - - /** - * Lists the members of a given activity. - * - * @param context The context object for the turn. - * @param activityId (Optional) Activity ID to enumerate. If not specified the current activities ID will be used. - * @return List of Members of the activity - */ - public CompletableFuture> GetActivityMembers(TurnContextImpl context) { - return GetActivityMembers(context, null); - } - - public CompletableFuture> GetActivityMembers(TurnContextImpl context, String activityId) { - // If no activity was passed in, use the current activity. - if (activityId == null) - activityId = context.getActivity().id(); - - if (context.getActivity().conversation() == null) - throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); - - if (StringUtils.isEmpty((context.getActivity().conversation().id()))) - throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); - - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - String conversationId = context.getActivity().conversation().id(); - - // TODO: - //List accounts = await(connectorClient.conversations().GetActivityMembersAsync(conversationId, activityId)); - - return completedFuture(null); - } - - /** - * Lists the members of the current conversation. - * - * @param context The context object for the turn. - * @return List of Members of the current conversation - */ - public CompletableFuture> GetConversationMembers(TurnContextImpl context) { - if (context.getActivity().conversation() == null) - throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); - - if (StringUtils.isEmpty(context.getActivity().conversation().id())) - throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); - - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - String conversationId = context.getActivity().conversation().id(); - - // TODO - //List accounts = await(connectorClient.conversations().getConversationMembersAsync(conversationId)); - return completedFuture(null); - } - - /** - * Lists the Conversations in which this bot has participated for a given channel server. The - * channel server returns results in pages and each page will include a `continuationToken` - * that can be used to fetch the next page of results from the server. - * - * @param serviceUrl The URL of the channel server to query. This can be retrieved - * from `context.activity.serviceUrl`. - * @param credentials The credentials needed for the Bot to connect to the.services(). - * @param continuationToken (Optional) token used to fetch the next page of results - * from the channel server. This should be left as `null` to retrieve the first page - * of results. - * @return List of Members of the current conversation - *

- * This overload may be called from outside the context of a conversation, as only the - * Bot's ServiceUrl and credentials are required. - */ - public CompletableFuture GetConversations(String serviceUrl, MicrosoftAppCredentials credentials) throws MalformedURLException, URISyntaxException { - return GetConversations(serviceUrl, credentials, null); - } - - public CompletableFuture GetConversations(String serviceUrl, MicrosoftAppCredentials credentials, String continuationToken) throws MalformedURLException, URISyntaxException { - if (StringUtils.isEmpty(serviceUrl)) - throw new IllegalArgumentException("serviceUrl"); - - if (credentials == null) - throw new IllegalArgumentException("credentials"); - - ConnectorClient connectorClient = this.CreateConnectorClient(serviceUrl, credentials); - // TODO - //ConversationsResult results = await(connectorClient.conversations().getConversationsAsync(continuationToken)); - return completedFuture(null); - } - - /** - * Lists the Conversations in which this bot has participated for a given channel server. The - * channel server returns results in pages and each page will include a `continuationToken` - * that can be used to fetch the next page of results from the server. - * - * @param context The context object for the turn. - * @param continuationToken (Optional) token used to fetch the next page of results - * from the channel server. This should be left as `null` to retrieve the first page - * of results. - * @return List of Members of the current conversation - *

- * This overload may be called during standard Activity processing, at which point the Bot's - * service URL and credentials that are part of the current activity processing pipeline - * will be used. - */ - public CompletableFuture GetConversations(TurnContextImpl context) { - return GetConversations(context, null); - } - - public CompletableFuture GetConversations(TurnContextImpl context, String continuationToken) { - ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - // TODO - //ConversationsResult results = await(connectorClient.conversations().getConversationsAsync()); - return completedFuture(null); - } - - - /** - * Attempts to retrieve the token for a user that's in a login flow. - * - * @param context Context for the current turn of conversation with the user. - * @param connectionName Name of the auth connection to use. - * @param magicCode (Optional) Optional user entered code to validate. - * @return Token Response - */ - public CompletableFuture GetUserToken(TurnContextImpl context, String connectionName, String magicCode) { - BotAssert.ContextNotNull(context); - if (context.getActivity().from() == null || StringUtils.isEmpty(context.getActivity().from().id())) - throw new IllegalArgumentException("BotFrameworkAdapter.GetuserToken(): missing from or from.id"); - - if (StringUtils.isEmpty(connectionName)) - throw new IllegalArgumentException("connectionName"); - - //OAuthClient client = this.CreateOAuthApiClient(context); - //return await(client.GetUserTokenAsync(context.getActivity().from().id(), connectionName, magicCode)); - return completedFuture(null); - } - - /** - * Get the raw signin link to be sent to the user for signin for a connection name. - * - * @param context Context for the current turn of conversation with the user. - * @param connectionName Name of the auth connection to use. - * @return - */ - public CompletableFuture GetOauthSignInLink(TurnContextImpl context, String connectionName) { - BotAssert.ContextNotNull(context); - if (StringUtils.isEmpty(connectionName)) - throw new IllegalArgumentException("connectionName"); - - //OAuthClient client = this.CreateOAuthApiClient(context); - //return await(client.GetSignInLinkAsync(context.getActivity(), connectionName)); - return completedFuture(null); - } - - /** - * Signs the user out with the token server. - * - * @param context Context for the current turn of conversation with the user. - * @param connectionName Name of the auth connection to use. - * @return - */ - public CompletableFuture SignOutUser(TurnContextImpl context, String connectionName) { - BotAssert.ContextNotNull(context); - if (StringUtils.isEmpty(connectionName)) - throw new IllegalArgumentException("connectionName"); - - //OAuthClient client = this.CreateOAuthApiClient(context); - //await(client.SignOutUserAsync(context.Activity.From.Id, connectionName)); - return completedFuture(null); - } - - /** - * Creates a conversation on the specified channel. - * - * @param channelId The ID for the channel. - * @param serviceUrl The channel's service URL endpoint. - * @param credentials The application credentials for the bot. - * @param conversationParameters The conversation information to use to - * create the conversation. - * @param callback The method to call for the resulting bot turn. - * @return A task that represents the work queued to execute. - * To start a conversation, your bot must know its account information - * and the user's account information on that channel. - * Most channels only support initiating a direct message (non-group) conversation. - *

The adapter attempts to create a new conversation on the channel, and - * then sends a {@code conversationUpdate} activity through its middleware pipeline - * to the {@code callback} method.

- *

If the conversation is established with the - * specified users, the ID of the activity's {@link Activity.Conversation} - * will contain the ID of the new conversation.

- */ - public CompletableFuture CreateConversation(String channelId, String serviceUrl, MicrosoftAppCredentials - credentials, ConversationParameters conversationParameters, Consumer callback) throws Exception { - // Validate serviceUrl - can throw - URI uri = new URI(serviceUrl); - return CompletableFuture.runAsync(() -> { - ConnectorClient connectorClient = null; - try { - connectorClient = this.CreateConnectorClient(serviceUrl, credentials); - } catch (MalformedURLException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad serviceUrl: %s", serviceUrl)); - } catch (URISyntaxException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad serviceUrl: %s", serviceUrl)); - } - - Conversations conv = connectorClient.conversations(); - List results = null; - if (conv instanceof ConversationsImpl) { - ConversationsImpl convImpl = (ConversationsImpl) conv; - results = convImpl.CreateConversationAsync(conversationParameters).join(); - } else { - results = new ArrayList(); - results.add(conv.createConversation(conversationParameters)); - } - if (results.size() == 1) { - - ConversationResourceResponse result = results.get(0); - // Create a conversation update activity to represent the result. - - ConversationUpdateActivity conversationUpdate = (ConversationUpdateActivity) MessageActivity.CreateConversationUpdateActivity() - .withChannelId(channelId) - .withTopicName(conversationParameters.topicName()) - .withServiceUrl(serviceUrl) - .withMembersAdded(conversationParameters.members()) - .withId((result.activityId() != null) ? result.activityId() : UUID.randomUUID().toString()) - .withConversation(new ConversationAccount().withId(result.id())) - .withRecipient(conversationParameters.bot()); - - try (TurnContextImpl context = new TurnContextImpl(this, conversationUpdate)) { - try { - this.RunPipeline(context, callback); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Running pipeline failed : %s", e)); - } - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Turn Context Error: %s", e)); - } - } else { - // Should never happen - throw new RuntimeException(String.format("Conversations create issue - returned %d conversations", results.size())); - } - }); - - } - - protected CompletableFuture TrySetEmulatingOAuthCards(TurnContext turnContext) { - if (!isEmulatingOAuthCards && - turnContext.getActivity().channelId().equals("emulator") && - (_credentialProvider.isAuthenticationDisabledAsync().join())) { - isEmulatingOAuthCards = true; - } - return completedFuture(isEmulatingOAuthCards); - - } - - protected OAuthClient CreateOAuthApiClient(TurnContext context) throws MalformedURLException, URISyntaxException { - ConnectorClientImpl client = context.getServices().Get("ConnectorClient"); - if (client == null) { - throw new IllegalArgumentException("CreateOAuthApiClient: OAuth requires a valid ConnectorClient instance"); - } - if (isEmulatingOAuthCards) { - return new OAuthClient(client, context.getActivity().serviceUrl()); - } - return new OAuthClient(client, AuthenticationConstants.OAuthUrl); - } - - /** - * Creates the connector client asynchronous. - * - * @param serviceUrl The service URL. - * @param claimsIdentity The claims identity. - * @return ConnectorClient instance. - * @throws UnsupportedOperationException ClaimsIdemtity cannot be null. Pass Anonymous ClaimsIdentity if authentication is turned off. - */ - private CompletableFuture CreateConnectorClientAsync(String serviceUrl, ClaimsIdentity claimsIdentity) { - - return CompletableFuture.supplyAsync(() -> { - if (claimsIdentity == null) { - throw new UnsupportedOperationException("ClaimsIdentity cannot be null. Pass Anonymous ClaimsIdentity if authentication is turned off."); - } - - // For requests from channel App Id is in Audience claim of JWT token. For emulator it is in AppId claim. For - // unauthenticated requests we have anonymous identity provided auth is disabled. - if (claimsIdentity.claims() == null) { - try { - return CreateConnectorClient(serviceUrl); - } catch (MalformedURLException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Invalid Service URL: %s", serviceUrl)); - } catch (URISyntaxException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Invalid Service URL: %s", serviceUrl)); - } - } - - // For Activities coming from Emulator AppId claim contains the Bot's AAD AppId. - // For anonymous requests (requests with no header) appId is not set in claims. - - Map.Entry botAppIdClaim = claimsIdentity.claims().entrySet().stream() - .filter(claim -> claim.getKey() == AuthenticationConstants.AudienceClaim) - .findFirst() - .orElse(null); - if (botAppIdClaim == null) { - botAppIdClaim = claimsIdentity.claims().entrySet().stream() - .filter(claim -> claim.getKey() == AuthenticationConstants.AppIdClaim) - .findFirst() - .orElse(null); - } - - if (botAppIdClaim != null) { - String botId = botAppIdClaim.getValue(); - MicrosoftAppCredentials appCredentials = this.GetAppCredentialsAsync(botId).join(); - try { - return this.CreateConnectorClient(serviceUrl, appCredentials); - } catch (MalformedURLException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); - } catch (URISyntaxException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); - } - } else { - try { - return this.CreateConnectorClient(serviceUrl); - } catch (MalformedURLException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); - } catch (URISyntaxException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); - } - } - }); - - } - - /** - * Creates the connector client. - * - * @param serviceUrl The service URL. - * @param appCredentials The application credentials for the bot. - * @return Connector client instance. - */ - private ConnectorClient CreateConnectorClient(String serviceUrl) throws MalformedURLException, URISyntaxException { - return CreateConnectorClient(serviceUrl, null); - } - - private ConnectorClient CreateConnectorClient(String serviceUrl, MicrosoftAppCredentials appCredentials) throws MalformedURLException, URISyntaxException { - ConnectorClientImpl connectorClient = null; - if (appCredentials != null) { - connectorClient = new ConnectorClientImpl(new URI(serviceUrl).toURL().toString(), appCredentials); - } - // TODO: Constructor necessary? -// else { -// -// connectorClient = new ConnectorClientImpl(new URI(serviceUrl).toURL().toString()); -// } - - if (this.connectorClientRetryStrategy != null) - connectorClient.withRestRetryStrategy(this.connectorClientRetryStrategy); - - - return connectorClient; - - } - - /** - * Gets the application credentials. App Credentials are cached so as to ensure we are not refreshing - * token everytime. - * - * @param appId The application identifier (AAD Id for the bot). - * @return App credentials. - */ - private CompletableFuture GetAppCredentialsAsync(String appId) { - CompletableFuture result = CompletableFuture.supplyAsync(() -> { - if (appId == null) { - return MicrosoftAppCredentials.Empty; - } - if (this.appCredentialMap.containsKey(appId)) - return this.appCredentialMap.get(appId); - String appPassword = this._credentialProvider.getAppPasswordAsync(appId).join(); - MicrosoftAppCredentials appCredentials = new MicrosoftAppCredentials(appId, appPassword); - this.appCredentialMap.put(appId, appCredentials); - return appCredentials; - - }); - return result; - } - -} +package com.microsoft.bot.builder; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import com.microsoft.bot.connector.ConnectorClient; +import com.microsoft.bot.connector.Conversations; +import com.microsoft.bot.connector.authentication.*; +import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.implementation.ConversationsImpl; +import com.microsoft.bot.schema.ActivityImpl; +import com.microsoft.bot.schema.models.*; +import com.microsoft.rest.retry.RetryStrategy; +import org.apache.commons.lang3.StringUtils; +import sun.net.www.http.HttpClient; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Function; + +import static java.util.concurrent.CompletableFuture.completedFuture; + +/** + * A bot adapter that can connect a bot to a service endpoint. + * The bot adapter encapsulates authentication processes and sends + * activities to and receives activities from the Bot Connector Service. When your + * bot receives an activity, the adapter creates a context object, passes it to your + * bot's application logic, and sends responses back to the user's channel. + *

Use {@link Use(Middleware)} to add {@link Middleware} objects + * to your adapter’s middleware collection. The adapter processes and directs + * incoming activities in through the bot middleware pipeline to your bot’s logic + * and then back out again. As each activity flows in and out of the bot, each piece + * of middleware can inspect or act upon the activity, both before and after the bot + * logic runs.

+ *

+ * {@linkalso TurnContext} + * {@linkalso Activity} + * {@linkalso Bot} + * {@linkalso Middleware} + */ +public class BotFrameworkAdapter extends BotAdapter { + private final CredentialProvider _credentialProvider; + + private final RetryStrategy connectorClientRetryStrategy; + private Map appCredentialMap = new HashMap(); + + private final String InvokeReponseKey = "BotFrameworkAdapter.InvokeResponse"; + private boolean isEmulatingOAuthCards = false; + + /** + * Initializes a new instance of the {@link BotFrameworkAdapter} class, + * using a credential provider. + * + * @param credentialProvider The credential provider. + * @param connectorClientRetryStrategy Retry strategy for retrying HTTP operations. + * @param httpClient The HTTP client. + * @param middleware The middleware to initially add to the adapter. + * @throws IllegalArgumentException {@code credentialProvider} is {@code null}. + * Use a {@link MiddlewareSet} object to add multiple middleware + * components in the conustructor. Use the {@link Use(Middleware)} method to + * add additional middleware to the adapter after construction. + */ + public BotFrameworkAdapter(CredentialProvider credentialProvider) { + this(credentialProvider, null, null, null); + } + + public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy) { + this(credentialProvider, connectorClientRetryStrategy, null, null); + } + + public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient) { + this(credentialProvider, connectorClientRetryStrategy, httpClient, null); + } + + public BotFrameworkAdapter(CredentialProvider credentialProvider, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient, Middleware middleware) { + if (credentialProvider == null) + throw new IllegalArgumentException("credentialProvider"); + _credentialProvider = credentialProvider; + //_httpClient = httpClient ?? new HttpClient(); + this.connectorClientRetryStrategy = connectorClientRetryStrategy; + + if (middleware != null) { + this.Use(middleware); + } + } + + /** + * Sends a proactive message from the bot to a conversation. + * + * @param botAppId The application ID of the bot. This is the appId returned by Portal registration, and is + * generally found in the "MicrosoftAppId" parameter in appSettings.json. + * @param reference A reference to the conversation to continue. + * @param callback The method to call for the resulting bot turn. + * @return A task that represents the work queued to execute. + * @throws IllegalArgumentException {@code botAppId}, {@code reference}, or + * {@code callback} is {@code null}. + * Call this method to proactively send a message to a conversation. + * Most channels require a user to initaiate a conversation with a bot + * before the bot can send activities to the user. + *

This method registers the following.services().for the turn. + * {@link ConnectorClient}, the channel connector client to use this turn. + *

+ *

+ * This overload differers from the Node implementation by requiring the BotId to be + * passed in. The .Net code allows multiple bots to be hosted in a single adapter which + * isn't something supported by Node. + *

+ *

+ * {@linkalso ProcessActivity(String, Activity, Func { TurnContext, Task })} + * {@linkalso BotAdapter.RunPipeline(TurnContext, Func { TurnContext, Task } } + */ + @Override + public void ContinueConversation(String botAppId, ConversationReference reference, Consumer callback) throws Exception { + if (StringUtils.isEmpty(botAppId)) + throw new IllegalArgumentException("botAppId"); + + if (reference == null) + throw new IllegalArgumentException("reference"); + + if (callback == null) + throw new IllegalArgumentException("callback"); + + try (TurnContextImpl context = new TurnContextImpl(this, new ConversationReferenceHelper(reference).GetPostToBotMessage())) { + // Hand craft Claims Identity. + HashMap claims = new HashMap(); + claims.put(AuthenticationConstants.AudienceClaim, botAppId); + claims.put(AuthenticationConstants.AppIdClaim, botAppId); + ClaimsIdentityImpl claimsIdentity = new ClaimsIdentityImpl("ExternalBearer", claims); + + context.getServices().Add("BotIdentity", claimsIdentity); + + ConnectorClient connectorClient = this.CreateConnectorClientAsync(reference.serviceUrl(), claimsIdentity).join(); + context.getServices().Add("ConnectorClient", connectorClient); + RunPipeline(context, callback); + } + return; + } + + /** + * Initializes a new instance of the {@link BotFrameworkAdapter} class, + * using an application ID and secret. + * + * @param appId The application ID of the bot. + * @param appPassword The application secret for the bot. + * @param connectorClientRetryStrategy Retry policy for retrying HTTP operations. + * @param httpClient The HTTP client. + * @param middleware The middleware to initially add to the adapter. + * Use a {@link MiddlewareSet} object to add multiple middleware + * components in the conustructor. Use the {@link Use(Middleware)} method to + * add additional middleware to the adapter after construction. + */ + public BotFrameworkAdapter(String appId, String appPassword) { + this(appId, appPassword, null, null, null); + } + + public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy) { + this(appId, appPassword, connectorClientRetryStrategy, null, null); + } + + public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient) { + this(appId, appPassword, connectorClientRetryStrategy, httpClient, null); + } + + public BotFrameworkAdapter(String appId, String appPassword, RetryStrategy connectorClientRetryStrategy, HttpClient httpClient, Middleware middleware) { + this(new SimpleCredentialProvider(appId, appPassword), connectorClientRetryStrategy, httpClient, middleware); + } + + /** + * Adds middleware to the adapter's pipeline. + * + * @param middleware The middleware to add. + * @return The updated adapter object. + * Middleware is added to the adapter at initialization time. + * For each turn, the adapter calls middleware in the order in which you added it. + */ + + public BotFrameworkAdapter Use(Middleware middleware) { + super._middlewareSet.Use(middleware); + return this; + } + + /** + * Creates a turn context and runs the middleware pipeline for an incoming activity. + * + * @param authHeader The HTTP authentication header of the request. + * @param activity The incoming activity. + * @param callback The code to run at the end of the adapter's middleware + * pipeline. + * @return A task that represents the work queued to execute. If the activity type + * was 'Invoke' and the corresponding key (channelId + activityId) was found + * then an InvokeResponse is returned, otherwise null is returned. + * @throws IllegalArgumentException {@code activity} is {@code null}. + * @throws UnauthorizedAccessException authentication failed. + * Call this method to reactively send a message to a conversation. + *

This method registers the following.services().for the turn. + * {@link ConnectorClient}, the channel connector client to use this turn. + *

+ *

+ * {@linkalso ContinueConversation(String, ConversationReference, Func { TurnContext, Task })} + * {@linkalso BotAdapter.RunPipeline(TurnContext, Func { TurnContext, Task })} + */ + public CompletableFuture ProcessActivity(String authHeader, ActivityImpl activity, Function callback) throws Exception { + BotAssert.ActivityNotNull(activity); + + //ClaimsIdentity claimsIdentity = await(JwtTokenValidation.validateAuthHeader(activity, authHeader, _credentialProvider)); + + //return completedFuture(await(ProcessActivity(claimsIdentity, activity, callback))); + return completedFuture(null); + } + + public CompletableFuture ProcessActivity(ClaimsIdentity identity, ActivityImpl activity, Consumer callback) throws Exception { + BotAssert.ActivityNotNull(activity); + + try (TurnContextImpl context = new TurnContextImpl(this, activity)) { + context.getServices().Add("BotIdentity", identity); + + ConnectorClient connectorClient = this.CreateConnectorClientAsync(activity.serviceUrl(), identity).join(); + // TODO: Verify key that C# uses + context.getServices().Add("ConnectorClient", connectorClient); + + super.RunPipeline(context, callback); + + // Handle Invoke scenarios, which deviate from the request/response model in that + // the Bot will return a specific body and return code. + if (activity.type() == ActivityTypes.INVOKE) { + Activity invokeResponse = context.getServices().Get(InvokeReponseKey); + if (invokeResponse == null) { + // ToDo: Trace Here + throw new IllegalStateException("Bot failed to return a valid 'invokeResponse' activity."); + } else { + return completedFuture((InvokeResponse) invokeResponse.value()); + } + } + + // For all non-invoke scenarios, the HTTP layers above don't have to mess + // withthe Body and return codes. + return null; + } + } + + /** + * Sends activities to the conversation. + * + * @param context The context object for the turn. + * @param activities The activities to send. + * @return A task that represents the work queued to execute. + * If the activities are successfully sent, the task result contains + * an array of {@link ResourceResponse} objects containing the IDs that + * the receiving channel assigned to the activities. + * {@linkalso TurnContext.OnSendActivities(SendActivitiesHandler)} + */ + public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { + if (context == null) { + throw new IllegalArgumentException("context"); + } + + if (activities == null) { + throw new IllegalArgumentException("activities"); + } + + if (activities.length == 0) { + throw new IllegalArgumentException("Expecting one or more activities, but the array was empty."); + } + + ResourceResponse[] responses = new ResourceResponse[activities.length]; + + /* + * NOTE: we're using for here (vs. foreach) because we want to simultaneously index into the + * activities array to get the activity to process as well as use that index to assign + * the response to the responses array and this is the most cost effective way to do that. + */ + for (int index = 0; index < activities.length; index++) { + Activity activity = activities[index]; + ResourceResponse response = new ResourceResponse(); + + if (activity.type().toString().equals("delay")) { + // The Activity Schema doesn't have a delay type build in, so it's simulated + // here in the Bot. This matches the behavior in the Node connector. + int delayMs = (int) activity.value(); + Thread.sleep(delayMs); + //await(Task.Delay(delayMs)); + // No need to create a response. One will be created below. + } else if (activity.type().toString().equals("invokeResponse")) // Aligning name with Node + { + context.getServices().Add(InvokeReponseKey, activity); + // No need to create a response. One will be created below. + } else if (activity.type() == ActivityTypes.TRACE && !activity.channelId().equals("emulator")) { + // if it is a Trace activity we only send to the channel if it's the emulator. + } else if (!StringUtils.isEmpty(activity.replyToId())) { + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + response = connectorClient.conversations().replyToActivity(activity.conversation().id(), activity.id(), activity); + } else { + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + response = connectorClient.conversations().sendToConversation(activity.conversation().id(), activity); + } + + // If No response is set, then defult to a "simple" response. This can't really be done + // above, as there are cases where the ReplyTo/SendTo methods will also return null + // (See below) so the check has to happen here. + + // Note: In addition to the Invoke / Delay / Activity cases, this code also applies + // with Skype and Teams with regards to typing events. When sending a typing event in + // these channels they do not return a RequestResponse which causes the bot to blow up. + // https://github.com/Microsoft/botbuilder-dotnet/issues/460 + // bug report : https://github.com/Microsoft/botbuilder-dotnet/issues/465 + if (response == null) { + response = new ResourceResponse().withId((activity.id() == null) ? "" : activity.id()); + } + + responses[index] = response; + } + + return responses; + } + + /** + * Replaces an existing activity in the conversation. + * + * @param context The context object for the turn. + * @param activity New replacement activity. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

Before calling this, set the ID of the replacement activity to the ID + * of the activity to replace.

+ * {@linkalso TurnContext.OnUpdateActivity(UpdateActivityHandler)} + */ + @Override + public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + // TODO String conversationId, String activityId, Activity activity) + return connectorClient.conversations().updateActivity(activity.conversation().id(), activity.id(), activity); + } + + /** + * Deletes an existing activity in the conversation. + * + * @param context The context object for the turn. + * @param reference Conversation reference for the activity to delete. + * @return A task that represents the work queued to execute. + * The {@link ConversationReference.ActivityId} of the conversation + * reference identifies the activity to delete. + * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} + */ + public void DeleteActivity(TurnContext context, ConversationReference reference) { + ConnectorClientImpl connectorClient = context.getServices().Get("ConnectorClient"); + try { + connectorClient.conversations().deleteConversationMemberFuture(reference.conversation().id(), reference.activityId()).join(); + } catch (ExecutionException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); + } + return; + } + + /** + * Deletes a member from the current conversation + * + * @param context The context object for the turn. + * @param memberId ID of the member to delete from the conversation + * @return + */ + public void DeleteConversationMember(TurnContextImpl context, String memberId) { + if (context.getActivity().conversation() == null) + throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation"); + + if (StringUtils.isEmpty(context.getActivity().conversation().id())) + throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation.id"); + + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + + String conversationId = context.getActivity().conversation().id(); + + // TODO: + //await (connectorClient.conversations().DeleteConversationMemberAsync(conversationId, memberId)); + return; + } + + /** + * Lists the members of a given activity. + * + * @param context The context object for the turn. + * @param activityId (Optional) Activity ID to enumerate. If not specified the current activities ID will be used. + * @return List of Members of the activity + */ + public CompletableFuture> GetActivityMembers(TurnContextImpl context) { + return GetActivityMembers(context, null); + } + + public CompletableFuture> GetActivityMembers(TurnContextImpl context, String activityId) { + // If no activity was passed in, use the current activity. + if (activityId == null) + activityId = context.getActivity().id(); + + if (context.getActivity().conversation() == null) + throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); + + if (StringUtils.isEmpty((context.getActivity().conversation().id()))) + throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); + + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + String conversationId = context.getActivity().conversation().id(); + + // TODO: + //List accounts = await(connectorClient.conversations().GetActivityMembersAsync(conversationId, activityId)); + + return completedFuture(null); + } + + /** + * Lists the members of the current conversation. + * + * @param context The context object for the turn. + * @return List of Members of the current conversation + */ + public CompletableFuture> GetConversationMembers(TurnContextImpl context) { + if (context.getActivity().conversation() == null) + throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); + + if (StringUtils.isEmpty(context.getActivity().conversation().id())) + throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); + + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + String conversationId = context.getActivity().conversation().id(); + + // TODO + //List accounts = await(connectorClient.conversations().getConversationMembersAsync(conversationId)); + return completedFuture(null); + } + + /** + * Lists the Conversations in which this bot has participated for a given channel server. The + * channel server returns results in pages and each page will include a `continuationToken` + * that can be used to fetch the next page of results from the server. + * + * @param serviceUrl The URL of the channel server to query. This can be retrieved + * from `context.activity.serviceUrl`. + * @param credentials The credentials needed for the Bot to connect to the.services(). + * @param continuationToken (Optional) token used to fetch the next page of results + * from the channel server. This should be left as `null` to retrieve the first page + * of results. + * @return List of Members of the current conversation + *

+ * This overload may be called from outside the context of a conversation, as only the + * Bot's ServiceUrl and credentials are required. + */ + public CompletableFuture GetConversations(String serviceUrl, MicrosoftAppCredentials credentials) throws MalformedURLException, URISyntaxException { + return GetConversations(serviceUrl, credentials, null); + } + + public CompletableFuture GetConversations(String serviceUrl, MicrosoftAppCredentials credentials, String continuationToken) throws MalformedURLException, URISyntaxException { + if (StringUtils.isEmpty(serviceUrl)) + throw new IllegalArgumentException("serviceUrl"); + + if (credentials == null) + throw new IllegalArgumentException("credentials"); + + ConnectorClient connectorClient = this.CreateConnectorClient(serviceUrl, credentials); + // TODO + //ConversationsResult results = await(connectorClient.conversations().getConversationsAsync(continuationToken)); + return completedFuture(null); + } + + /** + * Lists the Conversations in which this bot has participated for a given channel server. The + * channel server returns results in pages and each page will include a `continuationToken` + * that can be used to fetch the next page of results from the server. + * + * @param context The context object for the turn. + * @param continuationToken (Optional) token used to fetch the next page of results + * from the channel server. This should be left as `null` to retrieve the first page + * of results. + * @return List of Members of the current conversation + *

+ * This overload may be called during standard Activity processing, at which point the Bot's + * service URL and credentials that are part of the current activity processing pipeline + * will be used. + */ + public CompletableFuture GetConversations(TurnContextImpl context) { + return GetConversations(context, null); + } + + public CompletableFuture GetConversations(TurnContextImpl context, String continuationToken) { + ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); + // TODO + //ConversationsResult results = await(connectorClient.conversations().getConversationsAsync()); + return completedFuture(null); + } + + + /** + * Attempts to retrieve the token for a user that's in a login flow. + * + * @param context Context for the current turn of conversation with the user. + * @param connectionName Name of the auth connection to use. + * @param magicCode (Optional) Optional user entered code to validate. + * @return Token Response + */ + public CompletableFuture GetUserToken(TurnContextImpl context, String connectionName, String magicCode) { + BotAssert.ContextNotNull(context); + if (context.getActivity().from() == null || StringUtils.isEmpty(context.getActivity().from().id())) + throw new IllegalArgumentException("BotFrameworkAdapter.GetuserToken(): missing from or from.id"); + + if (StringUtils.isEmpty(connectionName)) + throw new IllegalArgumentException("connectionName"); + + //OAuthClient client = this.CreateOAuthApiClient(context); + //return await(client.GetUserTokenAsync(context.getActivity().from().id(), connectionName, magicCode)); + return completedFuture(null); + } + + /** + * Get the raw signin link to be sent to the user for signin for a connection name. + * + * @param context Context for the current turn of conversation with the user. + * @param connectionName Name of the auth connection to use. + * @return + */ + public CompletableFuture GetOauthSignInLink(TurnContextImpl context, String connectionName) { + BotAssert.ContextNotNull(context); + if (StringUtils.isEmpty(connectionName)) + throw new IllegalArgumentException("connectionName"); + + //OAuthClient client = this.CreateOAuthApiClient(context); + //return await(client.GetSignInLinkAsync(context.getActivity(), connectionName)); + return completedFuture(null); + } + + /** + * Signs the user out with the token server. + * + * @param context Context for the current turn of conversation with the user. + * @param connectionName Name of the auth connection to use. + * @return + */ + public CompletableFuture SignOutUser(TurnContextImpl context, String connectionName) { + BotAssert.ContextNotNull(context); + if (StringUtils.isEmpty(connectionName)) + throw new IllegalArgumentException("connectionName"); + + //OAuthClient client = this.CreateOAuthApiClient(context); + //await(client.SignOutUserAsync(context.Activity.From.Id, connectionName)); + return completedFuture(null); + } + + /** + * Creates a conversation on the specified channel. + * + * @param channelId The ID for the channel. + * @param serviceUrl The channel's service URL endpoint. + * @param credentials The application credentials for the bot. + * @param conversationParameters The conversation information to use to + * create the conversation. + * @param callback The method to call for the resulting bot turn. + * @return A task that represents the work queued to execute. + * To start a conversation, your bot must know its account information + * and the user's account information on that channel. + * Most channels only support initiating a direct message (non-group) conversation. + *

The adapter attempts to create a new conversation on the channel, and + * then sends a {@code conversationUpdate} activity through its middleware pipeline + * to the {@code callback} method.

+ *

If the conversation is established with the + * specified users, the ID of the activity's {@link Activity.Conversation} + * will contain the ID of the new conversation.

+ */ + public CompletableFuture CreateConversation(String channelId, String serviceUrl, MicrosoftAppCredentials + credentials, ConversationParameters conversationParameters, Consumer callback) throws Exception { + // Validate serviceUrl - can throw + URI uri = new URI(serviceUrl); + return CompletableFuture.runAsync(() -> { + ConnectorClient connectorClient = null; + try { + connectorClient = this.CreateConnectorClient(serviceUrl, credentials); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad serviceUrl: %s", serviceUrl)); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad serviceUrl: %s", serviceUrl)); + } + + Conversations conv = connectorClient.conversations(); + List results = null; + if (conv instanceof ConversationsImpl) { + ConversationsImpl convImpl = (ConversationsImpl) conv; + results = convImpl.CreateConversationAsync(conversationParameters).join(); + } else { + results = new ArrayList(); + results.add(conv.createConversation(conversationParameters)); + } + if (results.size() == 1) { + + ConversationResourceResponse result = results.get(0); + // Create a conversation update activity to represent the result. + + ConversationUpdateActivity conversationUpdate = (ConversationUpdateActivity) MessageActivity.CreateConversationUpdateActivity() + .withChannelId(channelId) + .withTopicName(conversationParameters.topicName()) + .withServiceUrl(serviceUrl) + .withMembersAdded(conversationParameters.members()) + .withId((result.activityId() != null) ? result.activityId() : UUID.randomUUID().toString()) + .withConversation(new ConversationAccount().withId(result.id())) + .withRecipient(conversationParameters.bot()); + + try (TurnContextImpl context = new TurnContextImpl(this, conversationUpdate)) { + try { + this.RunPipeline(context, callback); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Running pipeline failed : %s", e)); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Turn Context Error: %s", e)); + } + } else { + // Should never happen + throw new RuntimeException(String.format("Conversations create issue - returned %d conversations", results.size())); + } + }); + + } + + protected CompletableFuture TrySetEmulatingOAuthCards(TurnContext turnContext) { + if (!isEmulatingOAuthCards && + turnContext.getActivity().channelId().equals("emulator") && + (_credentialProvider.isAuthenticationDisabledAsync().join())) { + isEmulatingOAuthCards = true; + } + return completedFuture(isEmulatingOAuthCards); + + } + + protected OAuthClient CreateOAuthApiClient(TurnContext context) throws MalformedURLException, URISyntaxException { + ConnectorClientImpl client = context.getServices().Get("ConnectorClient"); + if (client == null) { + throw new IllegalArgumentException("CreateOAuthApiClient: OAuth requires a valid ConnectorClient instance"); + } + if (isEmulatingOAuthCards) { + return new OAuthClient(client, context.getActivity().serviceUrl()); + } + return new OAuthClient(client, AuthenticationConstants.OAuthUrl); + } + + /** + * Creates the connector client asynchronous. + * + * @param serviceUrl The service URL. + * @param claimsIdentity The claims identity. + * @return ConnectorClient instance. + * @throws UnsupportedOperationException ClaimsIdemtity cannot be null. Pass Anonymous ClaimsIdentity if authentication is turned off. + */ + private CompletableFuture CreateConnectorClientAsync(String serviceUrl, ClaimsIdentity claimsIdentity) { + + return CompletableFuture.supplyAsync(() -> { + if (claimsIdentity == null) { + throw new UnsupportedOperationException("ClaimsIdentity cannot be null. Pass Anonymous ClaimsIdentity if authentication is turned off."); + } + + // For requests from channel App Id is in Audience claim of JWT token. For emulator it is in AppId claim. For + // unauthenticated requests we have anonymous identity provided auth is disabled. + if (claimsIdentity.claims() == null) { + try { + return CreateConnectorClient(serviceUrl); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Invalid Service URL: %s", serviceUrl)); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Invalid Service URL: %s", serviceUrl)); + } + } + + // For Activities coming from Emulator AppId claim contains the Bot's AAD AppId. + // For anonymous requests (requests with no header) appId is not set in claims. + + Map.Entry botAppIdClaim = claimsIdentity.claims().entrySet().stream() + .filter(claim -> claim.getKey() == AuthenticationConstants.AudienceClaim) + .findFirst() + .orElse(null); + if (botAppIdClaim == null) { + botAppIdClaim = claimsIdentity.claims().entrySet().stream() + .filter(claim -> claim.getKey() == AuthenticationConstants.AppIdClaim) + .findFirst() + .orElse(null); + } + + if (botAppIdClaim != null) { + String botId = botAppIdClaim.getValue(); + MicrosoftAppCredentials appCredentials = this.GetAppCredentialsAsync(botId).join(); + try { + return this.CreateConnectorClient(serviceUrl, appCredentials); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); + } + } else { + try { + return this.CreateConnectorClient(serviceUrl); + } catch (MalformedURLException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); + } + } + }); + + } + + /** + * Creates the connector client. + * + * @param serviceUrl The service URL. + * @param appCredentials The application credentials for the bot. + * @return Connector client instance. + */ + private ConnectorClient CreateConnectorClient(String serviceUrl) throws MalformedURLException, URISyntaxException { + return CreateConnectorClient(serviceUrl, null); + } + + private ConnectorClient CreateConnectorClient(String serviceUrl, MicrosoftAppCredentials appCredentials) throws MalformedURLException, URISyntaxException { + ConnectorClientImpl connectorClient = null; + if (appCredentials != null) { + connectorClient = new ConnectorClientImpl(new URI(serviceUrl).toURL().toString(), appCredentials); + } + // TODO: Constructor necessary? +// else { +// +// connectorClient = new ConnectorClientImpl(new URI(serviceUrl).toURL().toString()); +// } + + if (this.connectorClientRetryStrategy != null) + connectorClient.withRestRetryStrategy(this.connectorClientRetryStrategy); + + + return connectorClient; + + } + + /** + * Gets the application credentials. App Credentials are cached so as to ensure we are not refreshing + * token everytime. + * + * @param appId The application identifier (AAD Id for the bot). + * @return App credentials. + */ + private CompletableFuture GetAppCredentialsAsync(String appId) { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + if (appId == null) { + return MicrosoftAppCredentials.empty(); + } + if (this.appCredentialMap.containsKey(appId)) + return this.appCredentialMap.get(appId); + String appPassword = this._credentialProvider.getAppPasswordAsync(appId).join(); + MicrosoftAppCredentials appCredentials = new MicrosoftAppCredentials(appId, appPassword); + this.appCredentialMap.put(appId, appCredentials); + return appCredentials; + + }); + return result; + } + +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java new file mode 100644 index 000000000..68c5742f3 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +package com.microsoft.bot.connector; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; +import java.util.concurrent.ForkJoinWorkerThread; + +/** + * Provides a common Executor for Future operations. + */ +public class ExecutorFactory { + private static ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory() { + @Override + public ForkJoinWorkerThread newThread(ForkJoinPool pool) { + ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); + worker.setName("Bot-" + worker.getPoolIndex()); + return worker; + } + }; + + private static ExecutorService executor= new ForkJoinPool( + Runtime.getRuntime().availableProcessors() * 2, + factory, + null, + false); + + public static ExecutorService getExecutor(){ + return executor; + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java new file mode 100644 index 000000000..0e07140c1 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +package com.microsoft.bot.connector.authentication; + +import com.microsoft.aad.adal4j.AuthenticationContext; +import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.aad.adal4j.ClientCredential; +import com.microsoft.bot.connector.ExecutorFactory; + +import java.net.MalformedURLException; +import java.util.concurrent.Future; + +public class AdalAuthenticator { + private AuthenticationContext context; + private OAuthConfiguration oAuthConfiguration; + private ClientCredential clientCredential; + + public AdalAuthenticator(ClientCredential clientCredential, OAuthConfiguration configurationOAuth) throws MalformedURLException { + this.oAuthConfiguration = configurationOAuth; + this.clientCredential = clientCredential; + this.context = new AuthenticationContext(configurationOAuth.authority(), false, ExecutorFactory.getExecutor()); + } + + public Future acquireToken(){ + return context.acquireToken(oAuthConfiguration.scope(), clientCredential, null); + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java index b8769b30c..e1b4b307a 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java @@ -7,23 +7,127 @@ import java.util.List; public final class AuthenticationConstants { - public static final String ToChannelFromBotLoginUrl = "https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token"; - public static final String ToChannelFromBotOAuthScope = "https://api.botframework.com/.default"; + /** + * TO CHANNEL FROM BOT: Login URL. + */ + @Deprecated + public static final String ToChannelFromBotLoginUrl = "https://login.microsoftonline.com/botframework.com"; + + /** + * TO CHANNEL FROM BOT: Login URL template string. Bot developer may specify + * which tenant to obtain an access token from. By default, the channels only + * accept tokens from "botframework.com". For more details see https://aka.ms/bots/tenant-restriction. + */ + public static final String ToChannelFromBotLoginUrlTemplate = "https://login.microsoftonline.com/%s"; + + /** + * TO CHANNEL FROM BOT: OAuth scope to request. + */ + public static final String ToChannelFromBotOAuthScope = "https://api.botframework.com"; + + /** + * TO BOT FROM CHANNEL: Token issuer. + */ public static final String ToBotFromChannelTokenIssuer = "https://api.botframework.com"; + + /** + * TO BOT FROM CHANNEL: OpenID metadata document for tokens coming from MSA. + */ public static final String ToBotFromChannelOpenIdMetadataUrl = "https://login.botframework.com/v1/.well-known/openidconfiguration"; + + /** + * TO BOT FROM EMULATOR: OpenID metadata document for tokens coming from MSA. + */ public static final String ToBotFromEmulatorOpenIdMetadataUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; + + /** + * TO BOT FROM ENTERPRISE CHANNEL: OpenID metadata document for tokens coming from MSA. + */ + public static final String ToBotFromEnterpriseChannelOpenIdMetadataUrlFormat = "https://%s.enterprisechannel.botframework.com/v1/.well-known/openidconfiguration"; + + /** + * Allowed token signing algorithms. Tokens come from channels to the bot. The code + * that uses this also supports tokens coming from the emulator. + */ public static final List AllowedSigningAlgorithms = new ArrayList<>(); + + /** + * Application Setting Key for the OAuthUrl value. + */ + public static final String OAuthUrlKey = "OAuthApiEndpoint"; + + /** + * OAuth Url used to get a token from OAuthApiClient. + */ + public static final String OAuthUrl = "https://api.botframework.com"; + + /** + * Application Settings Key for whether to emulate OAuthCards when using the emulator. + */ + public static final String EmulateOAuthCardsKey = "EmulateOAuthCards"; + + /** + * Application Setting Key for the OpenIdMetadataUrl value. + */ + public static final String BotOpenIdMetadataKey = "BotOpenIdMetadata"; + + /** + * The default tenant to acquire bot to channel token from. + */ + public static final String DefaultChannelAuthTenant = "botframework.com"; + + /** + * "azp" Claim. + * Authorized party - the party to which the ID Token was issued. + * This claim follows the general format set forth in the OpenID Spec. + * http://openid.net/specs/openid-connect-core-1_0.html#IDToken. + */ public static final String AuthorizedParty = "azp"; + + /** + * Audience Claim. From RFC 7519. + * https://tools.ietf.org/html/rfc7519#section-4.1.3 + * The "aud" (audience) claim identifies the recipients that the JWT is + * intended for. Each principal intended to process the JWT MUST + * identify itself with a value in the audience claim. If the principal + * processing the claim does not identify itself with a value in the + * "aud" claim when this claim is present, then the JWT MUST be + * rejected. In the general case, the "aud" value is an array of case- + * sensitive strings, each containing a StringOrURI value. In the + * special case when the JWT has one audience, the "aud" value MAY be a + * single case-sensitive string containing a StringOrURI value. The + * interpretation of audience values is generally application specific. + * Use of this claim is OPTIONAL. + */ public static final String AudienceClaim = "aud"; - public static final String ServiceUrlClaim = "serviceurl"; - public static final String VersionClaim = "ver"; - public static final String AppIdClaim = "appid"; + /** - * OAuth Url used to get a token from OAuthApiClient + * From RFC 7515 + * https://tools.ietf.org/html/rfc7515#section-4.1.4 + * The "kid" (key ID) Header Parameter is a hint indicating which key + * was used to secure the JWS. This parameter allows originators to + * explicitly signal a change of key to recipients. The structure of + * the "kid" value is unspecified. Its value MUST be a case-sensitive + * string. Use of this Header Parameter is OPTIONAL. + * When used with a JWK, the "kid" value is used to match a JWK "kid" + * parameter value. */ - public static final String OAuthUrl = "https://api.botframework.com"; + public static final String KeyIdHeader = "kid"; + /** + * Service URL claim name. As used in Microsoft Bot Framework v3.1 auth. + */ + public static final String ServiceUrlClaim = "serviceurl"; + /** + * Token version claim name. As used in Microsoft AAD tokens. + */ + public static final String VersionClaim = "ver"; + + /** + * App ID claim name. As used in Microsoft AAD 1.0 tokens. + */ + public static final String AppIdClaim = "appid"; static { AllowedSigningAlgorithms.add("RS256"); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index f4c54e513..9f991651c 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -4,110 +4,105 @@ package com.microsoft.bot.connector.authentication; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.aad.adal4j.ClientCredential; import com.microsoft.rest.credentials.ServiceClientCredentials; import okhttp3.*; +import org.slf4j.LoggerFactory; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.time.LocalDateTime; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Future; -import static com.microsoft.bot.connector.authentication.AuthenticationConstants.ToChannelFromBotLoginUrl; -import static com.microsoft.bot.connector.authentication.AuthenticationConstants.ToChannelFromBotOAuthScope; - +/** + * MicrosoftAppCredentials auth implementation + */ public class MicrosoftAppCredentials implements ServiceClientCredentials { - private String appId; - private String appPassword; - - private OkHttpClient client; - private ObjectMapper mapper; public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static final MediaType FORM_ENCODE = MediaType.parse("application/x-www-form-urlencoded"); - private String currentToken = null; - private long expiredTime = 0; - //private static final Object cacheSync = new Object(); - protected static final HashMap cache = new HashMap(); - - public final String OAuthEndpoint = ToChannelFromBotLoginUrl; - public final String OAuthScope = ToChannelFromBotOAuthScope; - + private String appId; + private String appPassword; + private String channelAuthTenant; + private AdalAuthenticator authenticator; - public String getTokenCacheKey() { - return String.format("%s-cache", this.appId); + public MicrosoftAppCredentials(String appId, String appPassword) { + this.appId = appId; + this.appPassword = appPassword; } - public MicrosoftAppCredentials(String appId, String appPassword) { + public MicrosoftAppCredentials(String appId, String appPassword, String channelAuthTenant) throws MalformedURLException { this.appId = appId; this.appPassword = appPassword; - this.client = new OkHttpClient.Builder().build(); - this.mapper = new ObjectMapper().findAndRegisterModules(); + setChannelAuthTenant(channelAuthTenant); } - public static final MicrosoftAppCredentials Empty = new MicrosoftAppCredentials(null, null); + public static MicrosoftAppCredentials empty() { + return new MicrosoftAppCredentials(null, null); + } - public String microsoftAppId() { + public String appId() { return this.appId; } + public String appPassword(){ return this.appPassword; } - public MicrosoftAppCredentials withMicrosoftAppId(String appId) { + public MicrosoftAppCredentials withAppId(String appId) { this.appId = appId; return this; } - public String getToken(Request request) throws IOException { - if (System.currentTimeMillis() < expiredTime) { - return currentToken; - } - Request reqToken = request.newBuilder() - .url(ToChannelFromBotLoginUrl) - .post(new FormBody.Builder() - .add("grant_type", "client_credentials") - .add("client_id", this.appId) - .add("client_secret", this.appPassword) - .add("scope", ToChannelFromBotOAuthScope) - .build()).build(); - Response response = this.client.newCall(reqToken).execute(); - if (response.isSuccessful()) { - String payload = response.body().string(); - AuthenticationResponse authResponse = this.mapper.readValue(payload, AuthenticationResponse.class); - this.expiredTime = System.currentTimeMillis() + (authResponse.expiresIn * 1000); - this.currentToken = authResponse.accessToken; - } - return this.currentToken; + public MicrosoftAppCredentials withAppPassword(String appPassword){ + this.appPassword = appPassword; + return this; } + public String channelAuthTenant(){ + return channelAuthTenant == null?AuthenticationConstants.DefaultChannelAuthTenant:channelAuthTenant; + } + + public void setChannelAuthTenant(String authTenant) throws MalformedURLException { + channelAuthTenant = (new URL(authTenant)).toString(); + } + + public MicrosoftAppCredentials withChannelAuthTenant(String authTenant) throws MalformedURLException { + setChannelAuthTenant(authTenant); + return this; + } + + public String oAuthEndpoint(){ + return String.format(AuthenticationConstants.ToChannelFromBotLoginUrlTemplate, channelAuthTenant()); + } + + public String oAuthScope(){ + return AuthenticationConstants.ToChannelFromBotOAuthScope; + } + + public Future getToken() throws MalformedURLException { + return getAuthenticator().acquireToken(); + } protected boolean ShouldSetToken(String url) { - if (isTrustedServiceUrl(url)) { - return true; - } - return false; + return isTrustedServiceUrl(url); } + private AdalAuthenticator getAuthenticator() throws MalformedURLException { + if(this.authenticator == null) { + this.authenticator = new AdalAuthenticator( + new ClientCredential(this.appId, this.appPassword), + new OAuthConfiguration(oAuthEndpoint(), oAuthScope())); + } + return this.authenticator; + } @Override public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) { clientBuilder.interceptors().add(new MicrosoftAppCredentialsInterceptor(this)); } - private static class AuthenticationResponse { - @JsonProperty(value = "token_type") - String tokenType; - @JsonProperty(value = "expires_in") - long expiresIn; - @JsonProperty(value = "ext_expires_in") - long extExpiresIn; - @JsonProperty(value = "access_token") - String accessToken; - } - - public static void trustServiceUrl(URI serviceUrl) { trustServiceUrl(serviceUrl.toString(), LocalDateTime.now().plusDays(1)); } @@ -121,8 +116,7 @@ public static void trustServiceUrl(String serviceUrl, LocalDateTime expirationTi URL url = new URL(serviceUrl); trustServiceUrl(url, expirationTime); } catch (MalformedURLException e) { - //TODO: What's missing here? - e.printStackTrace(); + LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); } } @@ -135,6 +129,7 @@ public static boolean isTrustedServiceUrl(String serviceUrl) { URL url = new URL(serviceUrl); return isTrustedServiceUrl(url); } catch (MalformedURLException e) { + LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); return false; } } @@ -150,6 +145,9 @@ public static boolean isTrustedServiceUrl(HttpUrl url) { private static ConcurrentMap trustHostNames = new ConcurrentHashMap<>(); static { - trustHostNames.put("state.botframework.com", LocalDateTime.MAX); + trustHostNames.put("api.botframework.com", LocalDateTime.MAX); + trustHostNames.put("token.botframework.com", LocalDateTime.MAX); + trustHostNames.put("api.botframework.azure.us", LocalDateTime.MAX); + trustHostNames.put("token.botframework.azure.us", LocalDateTime.MAX); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java index 793ad89b5..2e52de065 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java @@ -31,8 +31,15 @@ class MicrosoftAppCredentialsInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { if (MicrosoftAppCredentials.isTrustedServiceUrl(chain.request().url().url().toString())) { + String token; + try { + token = this.credentials.getToken().get().getAccessToken(); + } catch(Throwable t){ + throw new IOException(t); + } + Request newRequest = chain.request().newBuilder() - .header("Authorization", "Bearer " + this.credentials.getToken(chain.request())) + .header("Authorization", "Bearer " + token) .build(); return chain.proceed(newRequest); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java index 3263c79c8..0b10f9d49 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java @@ -246,7 +246,7 @@ public CompletableFuture GetSignInLinkAsync(Activity activity, String co .withConversation(activity.conversation()) .withServiceUrl(activity.serviceUrl()) .withUser(activity.from())) - .withMsAppId((creds == null) ? null : creds.microsoftAppId()); + .withMsAppId((creds == null) ? null : creds.appId()); String serializedState = this.mapper.writeValueAsString(tokenExchangeState); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java new file mode 100644 index 000000000..bff9076a1 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +package com.microsoft.bot.connector.authentication; + +/** + * Configuration for OAuth client credential authentication. + */ +public class OAuthConfiguration { + private String scope; + private String authority; + + public OAuthConfiguration(String authority, String scope){ + this.authority = authority; + this.scope = scope; + } + + /** + * Sets oAuth Authority for authentication. + * @param authority + * @return This OAuthConfiguration object. + */ + public OAuthConfiguration withAuthority(String authority){ + this.authority = authority; + return this; + } + + /** + * Gets oAuth Authority for authentication. + * @return OAuth Authority for authentication. + */ + public String authority(){ + return authority; + } + + /** + * Sets oAuth scope for authentication. + * @param scope + * @return This OAuthConfiguration object. + */ + public OAuthConfiguration withScope(String scope){ + this.scope = scope; + return this; + } + + /** + * Gets oAuth scope for authentication. + * @return OAuth scope for authentication. + */ + public String scope(){ + return scope; + } +} diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java index f8108fd3e..7bf891017 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java @@ -7,6 +7,7 @@ import org.junit.Assert; import org.junit.Test; import java.io.IOException; +import java.net.MalformedURLException; import java.util.concurrent.ExecutionException; public class BotAuthenticatorTest { @@ -140,8 +141,7 @@ public void ChannelAuthenticationDisabledServiceUrlShouldNotBeTrusted() throws E Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); } - private static String getHeaderToken() throws IOException { - Request request = new Request.Builder().url(AuthenticationConstants.ToChannelFromBotLoginUrl).build(); - return String.format("Bearer %s", new MicrosoftAppCredentials(AppId, AppPassword).getToken(request)); + private static String getHeaderToken() throws MalformedURLException, ExecutionException, InterruptedException { + return String.format("Bearer %s", new MicrosoftAppCredentials(AppId, AppPassword).getToken().get().getAccessToken()); } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index 0a934b147..c5d4da348 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -1,18 +1,29 @@ package com.microsoft.bot.connector; import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; +import com.microsoft.bot.connector.authentication.SimpleCredentialProvider; import org.junit.Assert; import org.junit.Test; +import java.net.MalformedURLException; +import java.util.concurrent.ExecutionException; + public class JwtTokenValidationTests { @Test public void Connector_AuthHeader_CorrectAppIdAndServiceUrl_ShouldValidate() - { -// MicrosoftAppCredentials credentials = new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F"); -// String header = "Bearer " + credentials. -// var credentials = new SimpleCredentialProvider("2cd87869-38a0-4182-9251-d056e8f0ac24", string.Empty); -// var result = await JwtTokenValidation.ValidateAuthHeader(header, credentials, new SimpleChannelProvider(), string.Empty, "https://webchat.botframework.com/", client); + throws MalformedURLException, ExecutionException, InterruptedException { + + MicrosoftAppCredentials credentials = new MicrosoftAppCredentials( + "2cd87869-38a0-4182-9251-d056e8f0ac24", + "2.30Vs3VQLKt974F"); + +// String header = "Bearer " + credentials.getToken().get().getAccessToken(); +// SimpleCredentialProvider credentials = new SimpleCredentialProvider( +// "2cd87869-38a0-4182-9251-d056e8f0ac24", +// null); // -// Assert.True(result.IsAuthenticated); +// JwtTokenValidation.ValidateAuthHeader(header, credentials, new SimpleChannelProvider(), null, "https://webchat.botframework.com/", client); + // + // Assert.True(result.IsAuthenticated); } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java index 9f3bf684d..8a5ac123c 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java @@ -74,7 +74,7 @@ protected void initializeClients(RestClient restClient, String botId, String use if (this.clientId != null && this.clientSecret != null) { MicrosoftAppCredentials credentials = new MicrosoftAppCredentials(this.clientId, this.clientSecret); - this.token = credentials.getToken(new Request.Builder().build()); + this.token = credentials.getToken().get().getAccessToken(); } else { this.token = null; From 139778b527347eaf4591783ac3f824d1a8ca63d6 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Fri, 16 Aug 2019 15:22:34 -0500 Subject: [PATCH 02/26] Removed inadvertent MicrosoftAppId and MicrosoftAppPassword from sample. --- samples/spring-echo/src/main/resources/application.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-echo/src/main/resources/application.properties b/samples/spring-echo/src/main/resources/application.properties index 653d80609..a695b3bf0 100644 --- a/samples/spring-echo/src/main/resources/application.properties +++ b/samples/spring-echo/src/main/resources/application.properties @@ -1,2 +1,2 @@ -MicrosoftAppId=9c286e2f-e070-4af5-a3f1-350d666214ed -MicrosoftAppPassword=botframework_secret_goes_here +MicrosoftAppId= +MicrosoftAppPassword= From 90b8b53baff48286aff63268b50f5b5a462fc078 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 20 Aug 2019 17:16:42 -0500 Subject: [PATCH 03/26] Implemented latest Connector Authorization (from dotnet) --- .../generators/app/templates/app.java | 2 +- .../bot/builder/BotFrameworkAdapter.java | 28 +- .../microsoft/bot/builder/BotStateTest.java | 758 ++++++------ .../bot/builder/MiddlewareSetTest.java | 1067 ++++++++--------- .../microsoft/bot/connector/Attachments.java | 42 +- .../com/microsoft/bot/connector/Channels.java | 91 ++ .../bot/connector/ConnectorClient.java | 4 +- .../bot/connector/ConnectorClientFuture.java | 41 - .../bot/connector/Conversations.java | 136 +-- .../bot/connector/ExecutorFactory.java | 5 +- .../microsoft/bot/connector/UserAgent.java | 4 +- .../authentication/AdalAuthenticator.java | 2 +- .../AuthenticationConfiguration.java | 16 + .../AuthenticationConstants.java | 36 +- .../authentication/BotCredentials.java | 23 - .../authentication/ChannelProvider.java | 34 + .../authentication/ChannelValidation.java | 135 ++- .../authentication/ClaimsIdentity.java | 43 +- .../authentication/ClaimsIdentityImpl.java | 40 - .../CredentialProviderImpl.java | 43 - .../authentication/EmulatorValidation.java | 165 +-- .../authentication/EndorsementsValidator.java | 17 +- .../EnterpriseChannelValidation.java | 115 ++ .../GovernmentAuthenticationConstants.java | 43 + .../GovernmentChannelValidation.java | 113 ++ .../authentication/JwtTokenExtractor.java | 52 +- .../authentication/JwtTokenValidation.java | 87 +- .../MicrosoftAppCredentials.java | 129 +- .../MicrosoftAppCredentialsInterceptor.java | 2 +- .../MicrosoftGovernmentAppCredentials.java | 43 + .../connector/authentication/OAuthClient.java | 91 +- .../authentication/OAuthConfiguration.java | 14 +- .../authentication/OpenIdMetadata.java | 18 +- .../authentication/ResponseFuture.java | 24 - .../authentication/SimpleChannelProvider.java | 45 + .../SimpleCredentialProvider.java | 26 +- .../TokenValidationParameters.java | 14 +- .../authentication/package-info.java | 8 + .../implementation/futureFromObservable.java | 2 - .../microsoft/bot/connector/package-info.java | 19 +- .../ErrorResponseException.java | 6 +- .../RestAttachments.java} | 13 +- .../RestConnectorClient.java} | 48 +- .../RestConversations.java} | 18 +- .../package-info.java | 2 +- .../bot/connector/BotAccessTokenStub.java | 10 - .../bot/connector/BotAuthenticatorTest.java | 147 --- .../bot/connector/BotConnectorTestBase.java | 6 +- .../bot/connector/ConversationsTest.java | 5 +- .../connector/EndorsementsValidatorTests.java | 3 + .../connector/JwtTokenValidationTests.java | 417 ++++++- .../bot/connector/OAuthConnectorTest.java | 16 +- .../bot/connector/OAuthTestBase.java | 13 +- libraries/bot-integration-core/pom.xml | 207 ++++ .../ClasspathPropertiesConfiguration.java | 30 + .../bot/integration/Configuration.java | 11 + .../ConfigurationChannelProvider.java | 18 + .../ConfigurationCredentialProvider.java | 17 + pom.xml | 1 + .../microsoft/bot/connector/sample/App.java | 14 +- .../bot/sample/servlet/EchoServlet.java | 15 +- .../bot/sample/spring/BotController.java | 15 +- 62 files changed, 2779 insertions(+), 1830 deletions(-) create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Channels.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClientFuture.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConfiguration.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/BotCredentials.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelProvider.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentityImpl.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProviderImpl.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftGovernmentAppCredentials.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ResponseFuture.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleChannelProvider.java create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/package-info.java delete mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/futureFromObservable.java rename libraries/bot-connector/src/main/java/com/microsoft/bot/connector/{models => rest}/ErrorResponseException.java (87%) rename libraries/bot-connector/src/main/java/com/microsoft/bot/connector/{implementation/AttachmentsImpl.java => rest/RestAttachments.java} (95%) rename libraries/bot-connector/src/main/java/com/microsoft/bot/connector/{implementation/ConnectorClientImpl.java => rest/RestConnectorClient.java} (81%) rename libraries/bot-connector/src/main/java/com/microsoft/bot/connector/{implementation/ConversationsImpl.java => rest/RestConversations.java} (99%) rename libraries/bot-connector/src/main/java/com/microsoft/bot/connector/{implementation => rest}/package-info.java (96%) delete mode 100644 libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java create mode 100644 libraries/bot-integration-core/pom.xml create mode 100644 libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java create mode 100644 libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java create mode 100644 libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java create mode 100644 libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java diff --git a/Generator/generator-botbuilder-java/generators/app/templates/app.java b/Generator/generator-botbuilder-java/generators/app/templates/app.java index 65584b463..c182c1422 100644 --- a/Generator/generator-botbuilder-java/generators/app/templates/app.java +++ b/Generator/generator-botbuilder-java/generators/app/templates/app.java @@ -10,7 +10,7 @@ import com.microsoft.bot.connector.customizations.CredentialProviderImpl; import com.microsoft.bot.connector.customizations.JwtTokenValidation; import com.microsoft.bot.connector.customizations.MicrosoftAppCredentials; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.ConnectorClientImpl; import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ActivityTypes; import com.microsoft.bot.schema.models.ResourceResponse; diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index 79e576f6b..11f41aa9c 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -6,8 +6,8 @@ import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.Conversations; import com.microsoft.bot.connector.authentication.*; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.bot.connector.implementation.ConversationsImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; +import com.microsoft.bot.connector.rest.RestConversations; import com.microsoft.bot.schema.ActivityImpl; import com.microsoft.bot.schema.models.*; import com.microsoft.rest.retry.RetryStrategy; @@ -129,9 +129,9 @@ public void ContinueConversation(String botAppId, ConversationReference referenc try (TurnContextImpl context = new TurnContextImpl(this, new ConversationReferenceHelper(reference).GetPostToBotMessage())) { // Hand craft Claims Identity. HashMap claims = new HashMap(); - claims.put(AuthenticationConstants.AudienceClaim, botAppId); - claims.put(AuthenticationConstants.AppIdClaim, botAppId); - ClaimsIdentityImpl claimsIdentity = new ClaimsIdentityImpl("ExternalBearer", claims); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, botAppId); + claims.put(AuthenticationConstants.APPID_CLAIM, botAppId); + ClaimsIdentity claimsIdentity = new ClaimsIdentity("ExternalBearer", claims); context.getServices().Add("BotIdentity", claimsIdentity); @@ -351,7 +351,7 @@ public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} */ public void DeleteActivity(TurnContext context, ConversationReference reference) { - ConnectorClientImpl connectorClient = context.getServices().Get("ConnectorClient"); + RestConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); try { connectorClient.conversations().deleteConversationMemberFuture(reference.conversation().id(), reference.activityId()).join(); } catch (ExecutionException e) { @@ -592,8 +592,8 @@ public CompletableFuture CreateConversation(String channelId, String serviceUrl, Conversations conv = connectorClient.conversations(); List results = null; - if (conv instanceof ConversationsImpl) { - ConversationsImpl convImpl = (ConversationsImpl) conv; + if (conv instanceof RestConversations) { + RestConversations convImpl = (RestConversations) conv; results = convImpl.CreateConversationAsync(conversationParameters).join(); } else { results = new ArrayList(); @@ -643,14 +643,14 @@ protected CompletableFuture TrySetEmulatingOAuthCards(TurnContext turnC } protected OAuthClient CreateOAuthApiClient(TurnContext context) throws MalformedURLException, URISyntaxException { - ConnectorClientImpl client = context.getServices().Get("ConnectorClient"); + RestConnectorClient client = context.getServices().Get("ConnectorClient"); if (client == null) { throw new IllegalArgumentException("CreateOAuthApiClient: OAuth requires a valid ConnectorClient instance"); } if (isEmulatingOAuthCards) { return new OAuthClient(client, context.getActivity().serviceUrl()); } - return new OAuthClient(client, AuthenticationConstants.OAuthUrl); + return new OAuthClient(client, AuthenticationConstants.OAUTH_URL); } /** @@ -686,12 +686,12 @@ private CompletableFuture CreateConnectorClientAsync(String ser // For anonymous requests (requests with no header) appId is not set in claims. Map.Entry botAppIdClaim = claimsIdentity.claims().entrySet().stream() - .filter(claim -> claim.getKey() == AuthenticationConstants.AudienceClaim) + .filter(claim -> claim.getKey() == AuthenticationConstants.AUDIENCE_CLAIM) .findFirst() .orElse(null); if (botAppIdClaim == null) { botAppIdClaim = claimsIdentity.claims().entrySet().stream() - .filter(claim -> claim.getKey() == AuthenticationConstants.AppIdClaim) + .filter(claim -> claim.getKey() == AuthenticationConstants.APPID_CLAIM) .findFirst() .orElse(null); } @@ -735,9 +735,9 @@ private ConnectorClient CreateConnectorClient(String serviceUrl) throws Malforme } private ConnectorClient CreateConnectorClient(String serviceUrl, MicrosoftAppCredentials appCredentials) throws MalformedURLException, URISyntaxException { - ConnectorClientImpl connectorClient = null; + RestConnectorClient connectorClient = null; if (appCredentials != null) { - connectorClient = new ConnectorClientImpl(new URI(serviceUrl).toURL().toString(), appCredentials); + connectorClient = new RestConnectorClient(new URI(serviceUrl).toURL().toString(), appCredentials); } // TODO: Constructor necessary? // else { diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java index 8b8587848..d344ec620 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java @@ -1,379 +1,379 @@ - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.builder; - - - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.microsoft.bot.builder.adapters.TestAdapter; -import com.microsoft.bot.builder.adapters.TestFlow; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ResourceResponse; -import com.microsoft.rest.RestClient; -import org.apache.commons.lang3.StringUtils; -import org.junit.Assert; -import org.junit.Test; - -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; - - -// [TestClass] -// [TestCategory("State Management")] -public class BotStateTest { - protected ConnectorClientImpl connector; - protected ChannelAccount bot; - protected ChannelAccount user; - - - protected void initializeClients(RestClient restClient, String botId, String userId) { - - connector = new ConnectorClientImpl(restClient); - bot = new ChannelAccount().withId(botId); - user = new ChannelAccount().withId(userId); - - } - - - protected void cleanUpResources() { - } - - @Test - public void State_DoNOTRememberContextState() throws ExecutionException, InterruptedException { - - TestAdapter adapter = new TestAdapter(); - - new TestFlow(adapter, (context) -> { - TestPocoState obj = StateTurnContextExtensions.GetConversationState(context); - Assert.assertNull("context.state should not exist", obj); } - ) - .Send("set value") - .StartTest(); - - } - - //@Test - public void State_RememberIStoreItemUserState() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new UserState(new MemoryStorage(), TestState::new)); - - - Consumer callback = (context) -> { - System.out.print(String.format("State_RememberIStoreItemUserState CALLBACK called..")); - System.out.flush(); - TestState userState = StateTurnContextExtensions.GetUserState(context); - Assert.assertNotNull("user state should exist", userState); - switch (context.getActivity().text()) { - case "set value": - userState.withValue("test"); - try { - ((TurnContextImpl)context).SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - Assert.assertFalse(StringUtils.isBlank(userState.value())); - ((TurnContextImpl)context).SendActivity(userState.value()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - - }; - - new TestFlow(adapter, callback) - .Test("set value", "value saved") - .Test("get value", "test") - .StartTest(); - - } - - @Test - public void State_RememberPocoUserState() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new UserState(new MemoryStorage(), TestPocoState::new)); - new TestFlow(adapter, - (context) -> - { - TestPocoState userState = StateTurnContextExtensions.GetUserState(context); - - Assert.assertNotNull("user state should exist", userState); - switch (context.getActivity().text()) { - case "set value": - userState.setValue("test"); - try { - context.SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - Assert.assertFalse(StringUtils.isBlank(userState.getValue())); - context.SendActivity(userState.getValue()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - .Test("set value", "value saved") - .Test("get value", "test") - .StartTest(); - } - - //@Test - public void State_RememberIStoreItemConversationState() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new ConversationState(new MemoryStorage(), TestState::new)); - new TestFlow(adapter, - (context) -> - { - TestState conversationState = StateTurnContextExtensions.GetConversationState(context); - Assert.assertNotNull("state.conversation should exist", conversationState); - switch (context.getActivity().text()) { - case "set value": - conversationState.withValue("test"); - try { - context.SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - Assert.assertFalse(StringUtils.isBlank(conversationState.value())); - context.SendActivity(conversationState.value()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - .Test("set value", "value saved") - .Test("get value", "test") - .StartTest(); - } - - //@Test - public void State_RememberPocoConversationState() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new ConversationState(new MemoryStorage(), TestPocoState::new)); - new TestFlow(adapter, - (context) -> - { - TestPocoState conversationState = StateTurnContextExtensions.GetConversationState(context); - Assert.assertNotNull("state.conversation should exist", conversationState); - switch (context.getActivity().text()) { - case "set value": - conversationState.setValue("test"); - try { - context.SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - Assert.assertFalse(StringUtils.isBlank(conversationState.getValue())); - context.SendActivity(conversationState.getValue()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - - .Test("set value", "value saved") - .Test("get value", "test") - .StartTest(); - } - - @Test - public void State_CustomStateManagerTest() throws ExecutionException, InterruptedException { - - String testGuid = UUID.randomUUID().toString(); - TestAdapter adapter = new TestAdapter() - .Use(new CustomKeyState(new MemoryStorage())); - new TestFlow(adapter, - (context) -> - { - CustomState customState = CustomKeyState.Get(context); - - switch (context.getActivity().text()) { - case "set value": - customState.setCustomString(testGuid); - try { - context.SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - Assert.assertFalse(StringUtils.isBlank(customState.getCustomString())); - context.SendActivity(customState.getCustomString()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - .Test("set value", "value saved") - .Test("get value", testGuid.toString()) - .StartTest(); - } - @Test - public void State_RoundTripTypedObjectwTrace() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new ConversationState(new MemoryStorage(), TypedObject::new)); - new TestFlow(adapter, - (context) -> - { - System.out.println(String.format(">>Test Callback(tid:%s): STARTING : %s", Thread.currentThread().getId(), context.getActivity().text())); - System.out.flush(); - TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); - Assert.assertNotNull("conversationstate should exist", conversation); - System.out.println(String.format(">>Test Callback(tid:%s): Text is : %s", Thread.currentThread().getId(), context.getActivity().text())); - System.out.flush(); - switch (context.getActivity().text()) { - case "set value": - conversation.withName("test"); - try { - System.out.println(String.format(">>Test Callback(tid:%s): Send activity : %s", Thread.currentThread().getId(), - "value saved")); - System.out.flush(); - ResourceResponse response = context.SendActivity("value saved"); - System.out.println(String.format(">>Test Callback(tid:%s): Response Id: %s", Thread.currentThread().getId(), - response.id())); - System.out.flush(); - - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - System.out.println(String.format(">>Test Callback(tid:%s): Send activity : %s", Thread.currentThread().getId(), - "TypedObject")); - System.out.flush(); - context.SendActivity("TypedObject"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - .Turn("set value", "value saved", "Description", 50000) - .Turn("get value", "TypedObject", "Description", 50000) - .StartTest(); - - } - - - @Test - public void State_RoundTripTypedObject() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter() - .Use(new ConversationState(new MemoryStorage(), TypedObject::new)); - - new TestFlow(adapter, - (context) -> - { - TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); - Assert.assertNotNull("conversationstate should exist", conversation); - switch (context.getActivity().text()) { - case "set value": - conversation.withName("test"); - try { - context.SendActivity("value saved"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - set value")); - } - break; - case "get value": - try { - context.SendActivity("TypedObject"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(String.format("Error sending activity! - get value")); - } - break; - } - }) - .Test("set value", "value saved") - .Test("get value", "TypedObject") - .StartTest(); - - } - - @Test - public void State_UseBotStateDirectly() throws ExecutionException, InterruptedException { - TestAdapter adapter = new TestAdapter(); - - new TestFlow(adapter, - (context) -> - { - BotState botStateManager = new BotState(new MemoryStorage(), "BotState:com.microsoft.bot.builder.core.extensions.BotState", - (ctx) -> String.format("botstate/%s/%s/com.microsoft.bot.builder.core.extensions.BotState", - ctx.getActivity().channelId(), ctx.getActivity().conversation().id()), CustomState::new); - - // read initial state object - CustomState customState = null; - try { - customState = (CustomState) botStateManager.Read(context).join(); - } catch (JsonProcessingException e) { - e.printStackTrace(); - Assert.fail("Error reading custom state"); - } - - // this should be a 'new CustomState' as nothing is currently stored in storage - Assert.assertEquals(customState, new CustomState()); - - // amend property and write to storage - customState.setCustomString("test"); - try { - botStateManager.Write(context, customState).join(); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail("Could not write customstate"); - } - - // set customState to null before reading from storage - customState = null; - try { - customState = (CustomState) botStateManager.Read(context).join(); - } catch (JsonProcessingException e) { - e.printStackTrace(); - Assert.fail("Could not read customstate back"); - } - - // check object read from value has the correct value for CustomString - Assert.assertEquals(customState.getCustomString(), "test"); - } - ) - .StartTest(); - } - - -} - + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.builder; + + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.microsoft.bot.builder.adapters.TestAdapter; +import com.microsoft.bot.builder.adapters.TestFlow; +import com.microsoft.bot.connector.rest.RestConnectorClient; +import com.microsoft.bot.schema.models.ChannelAccount; +import com.microsoft.bot.schema.models.ResourceResponse; +import com.microsoft.rest.RestClient; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; + + +// [TestClass] +// [TestCategory("State Management")] +public class BotStateTest { + protected RestConnectorClient connector; + protected ChannelAccount bot; + protected ChannelAccount user; + + + protected void initializeClients(RestClient restClient, String botId, String userId) { + + connector = new RestConnectorClient(restClient); + bot = new ChannelAccount().withId(botId); + user = new ChannelAccount().withId(userId); + + } + + + protected void cleanUpResources() { + } + + @Test + public void State_DoNOTRememberContextState() throws ExecutionException, InterruptedException { + + TestAdapter adapter = new TestAdapter(); + + new TestFlow(adapter, (context) -> { + TestPocoState obj = StateTurnContextExtensions.GetConversationState(context); + Assert.assertNull("context.state should not exist", obj); } + ) + .Send("set value") + .StartTest(); + + } + + //@Test + public void State_RememberIStoreItemUserState() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new UserState(new MemoryStorage(), TestState::new)); + + + Consumer callback = (context) -> { + System.out.print(String.format("State_RememberIStoreItemUserState CALLBACK called..")); + System.out.flush(); + TestState userState = StateTurnContextExtensions.GetUserState(context); + Assert.assertNotNull("user state should exist", userState); + switch (context.getActivity().text()) { + case "set value": + userState.withValue("test"); + try { + ((TurnContextImpl)context).SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + Assert.assertFalse(StringUtils.isBlank(userState.value())); + ((TurnContextImpl)context).SendActivity(userState.value()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + + }; + + new TestFlow(adapter, callback) + .Test("set value", "value saved") + .Test("get value", "test") + .StartTest(); + + } + + @Test + public void State_RememberPocoUserState() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new UserState(new MemoryStorage(), TestPocoState::new)); + new TestFlow(adapter, + (context) -> + { + TestPocoState userState = StateTurnContextExtensions.GetUserState(context); + + Assert.assertNotNull("user state should exist", userState); + switch (context.getActivity().text()) { + case "set value": + userState.setValue("test"); + try { + context.SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + Assert.assertFalse(StringUtils.isBlank(userState.getValue())); + context.SendActivity(userState.getValue()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + .Test("set value", "value saved") + .Test("get value", "test") + .StartTest(); + } + + //@Test + public void State_RememberIStoreItemConversationState() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new ConversationState(new MemoryStorage(), TestState::new)); + new TestFlow(adapter, + (context) -> + { + TestState conversationState = StateTurnContextExtensions.GetConversationState(context); + Assert.assertNotNull("state.conversation should exist", conversationState); + switch (context.getActivity().text()) { + case "set value": + conversationState.withValue("test"); + try { + context.SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + Assert.assertFalse(StringUtils.isBlank(conversationState.value())); + context.SendActivity(conversationState.value()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + .Test("set value", "value saved") + .Test("get value", "test") + .StartTest(); + } + + //@Test + public void State_RememberPocoConversationState() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new ConversationState(new MemoryStorage(), TestPocoState::new)); + new TestFlow(adapter, + (context) -> + { + TestPocoState conversationState = StateTurnContextExtensions.GetConversationState(context); + Assert.assertNotNull("state.conversation should exist", conversationState); + switch (context.getActivity().text()) { + case "set value": + conversationState.setValue("test"); + try { + context.SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + Assert.assertFalse(StringUtils.isBlank(conversationState.getValue())); + context.SendActivity(conversationState.getValue()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + + .Test("set value", "value saved") + .Test("get value", "test") + .StartTest(); + } + + @Test + public void State_CustomStateManagerTest() throws ExecutionException, InterruptedException { + + String testGuid = UUID.randomUUID().toString(); + TestAdapter adapter = new TestAdapter() + .Use(new CustomKeyState(new MemoryStorage())); + new TestFlow(adapter, + (context) -> + { + CustomState customState = CustomKeyState.Get(context); + + switch (context.getActivity().text()) { + case "set value": + customState.setCustomString(testGuid); + try { + context.SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + Assert.assertFalse(StringUtils.isBlank(customState.getCustomString())); + context.SendActivity(customState.getCustomString()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + .Test("set value", "value saved") + .Test("get value", testGuid.toString()) + .StartTest(); + } + @Test + public void State_RoundTripTypedObjectwTrace() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new ConversationState(new MemoryStorage(), TypedObject::new)); + new TestFlow(adapter, + (context) -> + { + System.out.println(String.format(">>Test Callback(tid:%s): STARTING : %s", Thread.currentThread().getId(), context.getActivity().text())); + System.out.flush(); + TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); + Assert.assertNotNull("conversationstate should exist", conversation); + System.out.println(String.format(">>Test Callback(tid:%s): Text is : %s", Thread.currentThread().getId(), context.getActivity().text())); + System.out.flush(); + switch (context.getActivity().text()) { + case "set value": + conversation.withName("test"); + try { + System.out.println(String.format(">>Test Callback(tid:%s): Send activity : %s", Thread.currentThread().getId(), + "value saved")); + System.out.flush(); + ResourceResponse response = context.SendActivity("value saved"); + System.out.println(String.format(">>Test Callback(tid:%s): Response Id: %s", Thread.currentThread().getId(), + response.id())); + System.out.flush(); + + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + System.out.println(String.format(">>Test Callback(tid:%s): Send activity : %s", Thread.currentThread().getId(), + "TypedObject")); + System.out.flush(); + context.SendActivity("TypedObject"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + .Turn("set value", "value saved", "Description", 50000) + .Turn("get value", "TypedObject", "Description", 50000) + .StartTest(); + + } + + + @Test + public void State_RoundTripTypedObject() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter() + .Use(new ConversationState(new MemoryStorage(), TypedObject::new)); + + new TestFlow(adapter, + (context) -> + { + TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); + Assert.assertNotNull("conversationstate should exist", conversation); + switch (context.getActivity().text()) { + case "set value": + conversation.withName("test"); + try { + context.SendActivity("value saved"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - set value")); + } + break; + case "get value": + try { + context.SendActivity("TypedObject"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(String.format("Error sending activity! - get value")); + } + break; + } + }) + .Test("set value", "value saved") + .Test("get value", "TypedObject") + .StartTest(); + + } + + @Test + public void State_UseBotStateDirectly() throws ExecutionException, InterruptedException { + TestAdapter adapter = new TestAdapter(); + + new TestFlow(adapter, + (context) -> + { + BotState botStateManager = new BotState(new MemoryStorage(), "BotState:com.microsoft.bot.builder.core.extensions.BotState", + (ctx) -> String.format("botstate/%s/%s/com.microsoft.bot.builder.core.extensions.BotState", + ctx.getActivity().channelId(), ctx.getActivity().conversation().id()), CustomState::new); + + // read initial state object + CustomState customState = null; + try { + customState = (CustomState) botStateManager.Read(context).join(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + Assert.fail("Error reading custom state"); + } + + // this should be a 'new CustomState' as nothing is currently stored in storage + Assert.assertEquals(customState, new CustomState()); + + // amend property and write to storage + customState.setCustomString("test"); + try { + botStateManager.Write(context, customState).join(); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail("Could not write customstate"); + } + + // set customState to null before reading from storage + customState = null; + try { + customState = (CustomState) botStateManager.Read(context).join(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + Assert.fail("Could not read customstate back"); + } + + // check object read from value has the correct value for CustomString + Assert.assertEquals(customState.getCustomString(), "test"); + } + ) + .StartTest(); + } + + +} + diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java index d289200d8..a4083f993 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java @@ -1,534 +1,533 @@ -package com.microsoft.bot.builder; - - -import com.microsoft.bot.builder.ActionDel; -import com.microsoft.bot.builder.base.TestBase; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.rest.RestClient; -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; - - -// [TestCategory("Russian Doll Middleware, Nested Middleware sets")] -public class MiddlewareSetTest extends TestBase -{ - protected ConnectorClientImpl connector; - protected ChannelAccount bot; - protected ChannelAccount user; - private boolean innerOnreceiveCalled; - - public MiddlewareSetTest() { - super(RunCondition.BOTH); - } - - @Override - protected void initializeClients(RestClient restClient, String botId, String userId) { - - connector = new ConnectorClientImpl(restClient); - bot = new ChannelAccount().withId(botId); - user = new ChannelAccount().withId(userId); - - // Test-specific stuff - innerOnreceiveCalled = false; - } - - @Override - protected void cleanUpResources() { - } - - - @Test - public void NoMiddleware() throws Exception { - MiddlewareSet m = new MiddlewareSet(); - // No middleware. Should not explode. - try { - m.ReceiveActivity(null); - Assert.assertTrue(true); - } catch (ExecutionException e) { - e.printStackTrace(); - Assert.fail("No exception expected" + e.getMessage()); - } catch (InterruptedException e) { - e.printStackTrace(); - Assert.fail("No exception expected" + e.getMessage()); - } - } - - - @Test - public void NestedSet_OnReceive() throws Exception { - final boolean[] wasCalled = {false}; - MiddlewareSet inner = new MiddlewareSet(); - inner.Use(new AnonymousReceiveMiddleware(new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - wasCalled[0] = true; - nd.next(); - } - })); - MiddlewareSet outer = new MiddlewareSet(); - outer.Use(inner); - try { - outer.ReceiveActivity(null); - } catch (ExecutionException e) { - Assert.fail(e.getMessage()); - return; - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - return; - } - - Assert.assertTrue("Inner Middleware Receive was not called.", wasCalled[0]); - } - - - @Test - public void NoMiddlewareWithDelegate() throws Exception { - MiddlewareSet m = new MiddlewareSet(); - final boolean wasCalled[] = {false}; - Consumer cb = context -> { - wasCalled[0] = true; - }; - // No middleware. Should not explode. - m.ReceiveActivityWithStatus(null, cb); - Assert.assertTrue("Delegate was not called", wasCalled[0]); - } - - @Test - public void OneMiddlewareItem() throws Exception { - WasCalledMiddlware simple = new WasCalledMiddlware(); - - final boolean wasCalled[] = {false}; - Consumer cb = context -> { - wasCalled[0] = true; - }; - - MiddlewareSet m = new MiddlewareSet(); - m.Use(simple); - - Assert.assertFalse(simple.getCalled()); - m.ReceiveActivityWithStatus(null, cb); - Assert.assertTrue(simple.getCalled()); - Assert.assertTrue( "Delegate was not called", wasCalled[0]); - } - - @Test - public void OneMiddlewareItemWithDelegate() throws Exception { - WasCalledMiddlware simple = new WasCalledMiddlware(); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(simple); - - Assert.assertFalse(simple.getCalled()); - m.ReceiveActivity(null); - Assert.assertTrue(simple.getCalled()); - } - - @Test(expected = IllegalStateException.class) - //[ExpectedException(typeof(InvalidOperationException))] - public void BubbleUncaughtException() throws Exception { - MiddlewareSet m = new MiddlewareSet(); - m.Use(new AnonymousReceiveMiddleware(new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws IllegalStateException { - throw new IllegalStateException("test"); - }} - )); - - m.ReceiveActivity(null); - Assert.assertFalse("Should never have gotten here", true); - } - - @Test - public void TwoMiddlewareItems() throws Exception { - WasCalledMiddlware one = new WasCalledMiddlware(); - WasCalledMiddlware two = new WasCalledMiddlware(); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - m.Use(two); - - m.ReceiveActivity(null); - Assert.assertTrue(one.getCalled()); - Assert.assertTrue(two.getCalled()); - } - - @Test - public void TwoMiddlewareItemsWithDelegate() throws Exception { - WasCalledMiddlware one = new WasCalledMiddlware(); - WasCalledMiddlware two = new WasCalledMiddlware(); - - final int called[] = {0}; - Consumer cb = (context) -> { - called[0]++; - }; - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - m.Use(two); - - m.ReceiveActivityWithStatus(null, cb); - Assert.assertTrue(one.getCalled()); - Assert.assertTrue(two.getCalled()); - Assert.assertTrue("Incorrect number of calls to Delegate", called[0] == 1 ); - } - - @Test - public void TwoMiddlewareItemsInOrder() throws Exception { - final boolean called1[] = {false}; - final boolean called2[] = {false}; - - CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { - @Override - public void CallMe() { - Assert.assertFalse( "Second Middleware was called", called2[0]); - called1[0] = true; - } - }); - - CallMeMiddlware two = new CallMeMiddlware(new ActionDel() { - @Override - public void CallMe() { - Assert.assertTrue("First Middleware was not called", called1[0]); - called2[0] = true; - } - }); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - m.Use(two); - - m.ReceiveActivity(null); - Assert.assertTrue(called1[0]); - Assert.assertTrue(called2[0]); - } - - @Test - public void Status_OneMiddlewareRan() throws Exception { - final boolean called1[] = {false}; - - CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { - @Override - public void CallMe() { - called1[0] = true; - } - }); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - - // The middlware in this pipeline calls next(), so the delegate should be called - final boolean didAllRun[] = {false}; - Consumer cb = (context) -> { - didAllRun[0] = true; - }; - m.ReceiveActivityWithStatus(null, cb); - - Assert.assertTrue(called1[0]); - Assert.assertTrue(didAllRun[0]); - } - - @Test - public void Status_RunAtEndEmptyPipeline() throws Exception { - MiddlewareSet m = new MiddlewareSet(); - final boolean didAllRun[] = {false}; - Consumer cb = (context)-> { - didAllRun[0] = true; - }; - - // This middlware pipeline has no entries. This should result in - // the status being TRUE. - m.ReceiveActivityWithStatus(null, cb); - Assert.assertTrue(didAllRun[0]); - - } - - @Test - public void Status_TwoItemsOneDoesNotCallNext() throws Exception { - final boolean called1[] = {false}; - final boolean called2[] = {false}; - - CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { - @Override - public void CallMe() { - Assert.assertFalse("Second Middleware was called", called2[0]); - called1[0] = true; - } - }); - - DoNotCallNextMiddleware two = new DoNotCallNextMiddleware(new ActionDel() { - @Override - public void CallMe() { - Assert.assertTrue("First Middleware was not called", called1[0]); - called2[0] = true; - }}); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - m.Use(two); - - boolean didAllRun[] = {false}; - Consumer cb= (context) -> { - didAllRun[0] = true; - }; - m.ReceiveActivityWithStatus(null, cb); - Assert.assertTrue(called1[0]); - Assert.assertTrue(called2[0]); - - // The 2nd middleware did not call next, so the "final" action should not have run. - Assert.assertFalse(didAllRun[0]); - } - - @Test - public void Status_OneEntryThatDoesNotCallNext() throws Exception { - final boolean called1[] = {false}; - - DoNotCallNextMiddleware one = new DoNotCallNextMiddleware(new ActionDel() { - @Override - public void CallMe() { - called1[0] = true; - } - }); - - MiddlewareSet m = new MiddlewareSet(); - m.Use(one); - - // The middleware in this pipeline DOES NOT call next(), so this must not be called - boolean didAllRun[] = {false}; - Consumer cb = (context) -> { - didAllRun[0] = true; - }; - m.ReceiveActivityWithStatus(null, cb); - - Assert.assertTrue(called1[0]); - - // Our "Final" action MUST NOT have been called, as the Middlware Pipeline - // didn't complete. - Assert.assertFalse(didAllRun[0]); - } - - @Test - public void AnonymousMiddleware() throws Exception { - final boolean didRun[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - MiddlewareCall mwc = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - didRun[0] = true; - nd.next(); - return; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc)); - - Assert.assertFalse(didRun[0]); - m.ReceiveActivity(null); - Assert.assertTrue(didRun[0]); - } - - @Test - public void TwoAnonymousMiddleware() throws Exception { - final boolean didRun1[] = {false}; - final boolean didRun2[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - didRun1[0] = true; - nd.next(); - return; - } - }; - - m.Use(new AnonymousReceiveMiddleware(mwc1)); - MiddlewareCall mwc2 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - didRun2[0] = true; - nd.next(); - return; - } - }; - - m.Use(new AnonymousReceiveMiddleware(mwc2)); - - m.ReceiveActivity(null); - Assert.assertTrue(didRun1[0]); - Assert.assertTrue(didRun2[0]); - } - - @Test - public void TwoAnonymousMiddlewareInOrder() throws Exception { - final boolean didRun1[] = {false}; - final boolean didRun2[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertFalse("Looks like the 2nd one has already run", didRun2[0]); - didRun1[0] = true; - nd.next(); - return; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc1)); - - MiddlewareCall mwc2 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertTrue("Looks like the 1nd one has not yet run", didRun1[0]); - didRun2[0] = true; - nd.next(); - return ; - } - }; - - m.Use(new AnonymousReceiveMiddleware(mwc2)); - - m.ReceiveActivity(null); - Assert.assertTrue(didRun1[0]); - Assert.assertTrue(didRun2[0]); - } - - @Test - public void MixedMiddlewareInOrderAnonymousFirst() throws Exception { - final boolean didRun1[] = {false}; - final boolean didRun2[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertFalse("First middleware already ran", didRun1[0]); - Assert.assertFalse("Looks like the second middleware was already run", didRun2[0]); - didRun1[0] = true; - nd.next(); - Assert.assertTrue("Second middleware should have completed running", didRun2[0]); - return ; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc1)); - - ActionDel act = new ActionDel() { - @Override - public void CallMe() { - Assert.assertTrue("First middleware should have already been called", didRun1[0]); - Assert.assertFalse("Second middleware should not have been invoked yet", didRun2[0]); - didRun2[0] = true; - } - }; - m.Use(new CallMeMiddlware(act)); - - m.ReceiveActivity(null); - Assert.assertTrue(didRun1[0]); - Assert.assertTrue(didRun2[0]); - } - - @Test - public void MixedMiddlewareInOrderAnonymousLast() throws Exception { - final boolean didRun1[] = {false}; - final boolean didRun2[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - - ActionDel act = new ActionDel() { - @Override - public void CallMe() { - Assert.assertFalse("First middleware should not have already been called", didRun1[0]); - Assert.assertFalse("Second middleware should not have been invoked yet", didRun2[0]); - didRun1[0] = true; - } - }; - m.Use(new CallMeMiddlware(act)); - - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertTrue("First middleware has not been run yet", didRun1[0]); - didRun2[0] = true; - nd.next(); - return; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc1)); - - m.ReceiveActivity(null); - Assert.assertTrue(didRun1[0]); - Assert.assertTrue(didRun2[0]); - } - - @Test - public void RunCodeBeforeAndAfter() throws Exception { - final boolean didRun1[] = {false}; - final boolean codeafter2run[] = {false}; - final boolean didRun2[] = {false}; - - MiddlewareSet m = new MiddlewareSet(); - - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertFalse("Looks like the 1st middleware has already run", didRun1[0]); - didRun1[0] = true; - nd.next(); - Assert.assertTrue("The 2nd middleware should have run now.", didRun1[0]); - codeafter2run[0] = true; - return ; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc1)); - - MiddlewareCall mwc2 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { - Assert.assertTrue("Looks like the 1st middleware has not been run", didRun1[0]); - Assert.assertFalse("The code that runs after middleware 2 is complete has already run.", codeafter2run[0]); - didRun2[0] = true; - nd.next(); - return ; - } - }; - m.Use(new AnonymousReceiveMiddleware(mwc2)); - - m.ReceiveActivity(null); - Assert.assertTrue(didRun1[0]); - Assert.assertTrue(didRun2[0]); - Assert.assertTrue(codeafter2run[0]); - } - - @Test - public void CatchAnExceptionViaMiddlware() throws Exception { - MiddlewareSet m = new MiddlewareSet(); - final boolean caughtException[] = {false}; - - MiddlewareCall mwc1 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws ExecutionException, InterruptedException { - try { - nd.next(); - Assert.assertTrue("Should not get here", false); - - } - catch (InterruptedException ex) { - System.out.println("Here isi the exception message" + ex.getMessage()); - System.out.flush(); - Assert.assertTrue(ex.getMessage() == "test"); - - caughtException[0] = true; - } catch (Exception e) { - Assert.assertTrue("Should not get here" + e.getMessage(), false); - } - return ; - }}; - - m.Use(new AnonymousReceiveMiddleware(mwc1)); - - MiddlewareCall mwc2 = new MiddlewareCall() { - public void requestHandler(TurnContext tc, NextDelegate nd) throws InterruptedException { - throw new InterruptedException("test"); - } - }; - - m.Use(new AnonymousReceiveMiddleware(mwc2)); - - m.ReceiveActivity(null); - Assert.assertTrue(caughtException[0]); - } - - - -} +package com.microsoft.bot.builder; + + +import com.microsoft.bot.builder.base.TestBase; +import com.microsoft.bot.connector.rest.RestConnectorClient; +import com.microsoft.bot.schema.models.ChannelAccount; +import com.microsoft.rest.RestClient; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; + + +// [TestCategory("Russian Doll Middleware, Nested Middleware sets")] +public class MiddlewareSetTest extends TestBase +{ + protected RestConnectorClient connector; + protected ChannelAccount bot; + protected ChannelAccount user; + private boolean innerOnreceiveCalled; + + public MiddlewareSetTest() { + super(RunCondition.BOTH); + } + + @Override + protected void initializeClients(RestClient restClient, String botId, String userId) { + + connector = new RestConnectorClient(restClient); + bot = new ChannelAccount().withId(botId); + user = new ChannelAccount().withId(userId); + + // Test-specific stuff + innerOnreceiveCalled = false; + } + + @Override + protected void cleanUpResources() { + } + + + @Test + public void NoMiddleware() throws Exception { + MiddlewareSet m = new MiddlewareSet(); + // No middleware. Should not explode. + try { + m.ReceiveActivity(null); + Assert.assertTrue(true); + } catch (ExecutionException e) { + e.printStackTrace(); + Assert.fail("No exception expected" + e.getMessage()); + } catch (InterruptedException e) { + e.printStackTrace(); + Assert.fail("No exception expected" + e.getMessage()); + } + } + + + @Test + public void NestedSet_OnReceive() throws Exception { + final boolean[] wasCalled = {false}; + MiddlewareSet inner = new MiddlewareSet(); + inner.Use(new AnonymousReceiveMiddleware(new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + wasCalled[0] = true; + nd.next(); + } + })); + MiddlewareSet outer = new MiddlewareSet(); + outer.Use(inner); + try { + outer.ReceiveActivity(null); + } catch (ExecutionException e) { + Assert.fail(e.getMessage()); + return; + } catch (InterruptedException e) { + Assert.fail(e.getMessage()); + return; + } + + Assert.assertTrue("Inner Middleware Receive was not called.", wasCalled[0]); + } + + + @Test + public void NoMiddlewareWithDelegate() throws Exception { + MiddlewareSet m = new MiddlewareSet(); + final boolean wasCalled[] = {false}; + Consumer cb = context -> { + wasCalled[0] = true; + }; + // No middleware. Should not explode. + m.ReceiveActivityWithStatus(null, cb); + Assert.assertTrue("Delegate was not called", wasCalled[0]); + } + + @Test + public void OneMiddlewareItem() throws Exception { + WasCalledMiddlware simple = new WasCalledMiddlware(); + + final boolean wasCalled[] = {false}; + Consumer cb = context -> { + wasCalled[0] = true; + }; + + MiddlewareSet m = new MiddlewareSet(); + m.Use(simple); + + Assert.assertFalse(simple.getCalled()); + m.ReceiveActivityWithStatus(null, cb); + Assert.assertTrue(simple.getCalled()); + Assert.assertTrue( "Delegate was not called", wasCalled[0]); + } + + @Test + public void OneMiddlewareItemWithDelegate() throws Exception { + WasCalledMiddlware simple = new WasCalledMiddlware(); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(simple); + + Assert.assertFalse(simple.getCalled()); + m.ReceiveActivity(null); + Assert.assertTrue(simple.getCalled()); + } + + @Test(expected = IllegalStateException.class) + //[ExpectedException(typeof(InvalidOperationException))] + public void BubbleUncaughtException() throws Exception { + MiddlewareSet m = new MiddlewareSet(); + m.Use(new AnonymousReceiveMiddleware(new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws IllegalStateException { + throw new IllegalStateException("test"); + }} + )); + + m.ReceiveActivity(null); + Assert.assertFalse("Should never have gotten here", true); + } + + @Test + public void TwoMiddlewareItems() throws Exception { + WasCalledMiddlware one = new WasCalledMiddlware(); + WasCalledMiddlware two = new WasCalledMiddlware(); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + m.Use(two); + + m.ReceiveActivity(null); + Assert.assertTrue(one.getCalled()); + Assert.assertTrue(two.getCalled()); + } + + @Test + public void TwoMiddlewareItemsWithDelegate() throws Exception { + WasCalledMiddlware one = new WasCalledMiddlware(); + WasCalledMiddlware two = new WasCalledMiddlware(); + + final int called[] = {0}; + Consumer cb = (context) -> { + called[0]++; + }; + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + m.Use(two); + + m.ReceiveActivityWithStatus(null, cb); + Assert.assertTrue(one.getCalled()); + Assert.assertTrue(two.getCalled()); + Assert.assertTrue("Incorrect number of calls to Delegate", called[0] == 1 ); + } + + @Test + public void TwoMiddlewareItemsInOrder() throws Exception { + final boolean called1[] = {false}; + final boolean called2[] = {false}; + + CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { + @Override + public void CallMe() { + Assert.assertFalse( "Second Middleware was called", called2[0]); + called1[0] = true; + } + }); + + CallMeMiddlware two = new CallMeMiddlware(new ActionDel() { + @Override + public void CallMe() { + Assert.assertTrue("First Middleware was not called", called1[0]); + called2[0] = true; + } + }); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + m.Use(two); + + m.ReceiveActivity(null); + Assert.assertTrue(called1[0]); + Assert.assertTrue(called2[0]); + } + + @Test + public void Status_OneMiddlewareRan() throws Exception { + final boolean called1[] = {false}; + + CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { + @Override + public void CallMe() { + called1[0] = true; + } + }); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + + // The middlware in this pipeline calls next(), so the delegate should be called + final boolean didAllRun[] = {false}; + Consumer cb = (context) -> { + didAllRun[0] = true; + }; + m.ReceiveActivityWithStatus(null, cb); + + Assert.assertTrue(called1[0]); + Assert.assertTrue(didAllRun[0]); + } + + @Test + public void Status_RunAtEndEmptyPipeline() throws Exception { + MiddlewareSet m = new MiddlewareSet(); + final boolean didAllRun[] = {false}; + Consumer cb = (context)-> { + didAllRun[0] = true; + }; + + // This middlware pipeline has no entries. This should result in + // the status being TRUE. + m.ReceiveActivityWithStatus(null, cb); + Assert.assertTrue(didAllRun[0]); + + } + + @Test + public void Status_TwoItemsOneDoesNotCallNext() throws Exception { + final boolean called1[] = {false}; + final boolean called2[] = {false}; + + CallMeMiddlware one = new CallMeMiddlware(new ActionDel() { + @Override + public void CallMe() { + Assert.assertFalse("Second Middleware was called", called2[0]); + called1[0] = true; + } + }); + + DoNotCallNextMiddleware two = new DoNotCallNextMiddleware(new ActionDel() { + @Override + public void CallMe() { + Assert.assertTrue("First Middleware was not called", called1[0]); + called2[0] = true; + }}); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + m.Use(two); + + boolean didAllRun[] = {false}; + Consumer cb= (context) -> { + didAllRun[0] = true; + }; + m.ReceiveActivityWithStatus(null, cb); + Assert.assertTrue(called1[0]); + Assert.assertTrue(called2[0]); + + // The 2nd middleware did not call next, so the "final" action should not have run. + Assert.assertFalse(didAllRun[0]); + } + + @Test + public void Status_OneEntryThatDoesNotCallNext() throws Exception { + final boolean called1[] = {false}; + + DoNotCallNextMiddleware one = new DoNotCallNextMiddleware(new ActionDel() { + @Override + public void CallMe() { + called1[0] = true; + } + }); + + MiddlewareSet m = new MiddlewareSet(); + m.Use(one); + + // The middleware in this pipeline DOES NOT call next(), so this must not be called + boolean didAllRun[] = {false}; + Consumer cb = (context) -> { + didAllRun[0] = true; + }; + m.ReceiveActivityWithStatus(null, cb); + + Assert.assertTrue(called1[0]); + + // Our "Final" action MUST NOT have been called, as the Middlware Pipeline + // didn't complete. + Assert.assertFalse(didAllRun[0]); + } + + @Test + public void AnonymousMiddleware() throws Exception { + final boolean didRun[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + MiddlewareCall mwc = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + didRun[0] = true; + nd.next(); + return; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc)); + + Assert.assertFalse(didRun[0]); + m.ReceiveActivity(null); + Assert.assertTrue(didRun[0]); + } + + @Test + public void TwoAnonymousMiddleware() throws Exception { + final boolean didRun1[] = {false}; + final boolean didRun2[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + didRun1[0] = true; + nd.next(); + return; + } + }; + + m.Use(new AnonymousReceiveMiddleware(mwc1)); + MiddlewareCall mwc2 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + didRun2[0] = true; + nd.next(); + return; + } + }; + + m.Use(new AnonymousReceiveMiddleware(mwc2)); + + m.ReceiveActivity(null); + Assert.assertTrue(didRun1[0]); + Assert.assertTrue(didRun2[0]); + } + + @Test + public void TwoAnonymousMiddlewareInOrder() throws Exception { + final boolean didRun1[] = {false}; + final boolean didRun2[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertFalse("Looks like the 2nd one has already run", didRun2[0]); + didRun1[0] = true; + nd.next(); + return; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc1)); + + MiddlewareCall mwc2 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertTrue("Looks like the 1nd one has not yet run", didRun1[0]); + didRun2[0] = true; + nd.next(); + return ; + } + }; + + m.Use(new AnonymousReceiveMiddleware(mwc2)); + + m.ReceiveActivity(null); + Assert.assertTrue(didRun1[0]); + Assert.assertTrue(didRun2[0]); + } + + @Test + public void MixedMiddlewareInOrderAnonymousFirst() throws Exception { + final boolean didRun1[] = {false}; + final boolean didRun2[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertFalse("First middleware already ran", didRun1[0]); + Assert.assertFalse("Looks like the second middleware was already run", didRun2[0]); + didRun1[0] = true; + nd.next(); + Assert.assertTrue("Second middleware should have completed running", didRun2[0]); + return ; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc1)); + + ActionDel act = new ActionDel() { + @Override + public void CallMe() { + Assert.assertTrue("First middleware should have already been called", didRun1[0]); + Assert.assertFalse("Second middleware should not have been invoked yet", didRun2[0]); + didRun2[0] = true; + } + }; + m.Use(new CallMeMiddlware(act)); + + m.ReceiveActivity(null); + Assert.assertTrue(didRun1[0]); + Assert.assertTrue(didRun2[0]); + } + + @Test + public void MixedMiddlewareInOrderAnonymousLast() throws Exception { + final boolean didRun1[] = {false}; + final boolean didRun2[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + + ActionDel act = new ActionDel() { + @Override + public void CallMe() { + Assert.assertFalse("First middleware should not have already been called", didRun1[0]); + Assert.assertFalse("Second middleware should not have been invoked yet", didRun2[0]); + didRun1[0] = true; + } + }; + m.Use(new CallMeMiddlware(act)); + + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertTrue("First middleware has not been run yet", didRun1[0]); + didRun2[0] = true; + nd.next(); + return; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc1)); + + m.ReceiveActivity(null); + Assert.assertTrue(didRun1[0]); + Assert.assertTrue(didRun2[0]); + } + + @Test + public void RunCodeBeforeAndAfter() throws Exception { + final boolean didRun1[] = {false}; + final boolean codeafter2run[] = {false}; + final boolean didRun2[] = {false}; + + MiddlewareSet m = new MiddlewareSet(); + + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertFalse("Looks like the 1st middleware has already run", didRun1[0]); + didRun1[0] = true; + nd.next(); + Assert.assertTrue("The 2nd middleware should have run now.", didRun1[0]); + codeafter2run[0] = true; + return ; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc1)); + + MiddlewareCall mwc2 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws Exception { + Assert.assertTrue("Looks like the 1st middleware has not been run", didRun1[0]); + Assert.assertFalse("The code that runs after middleware 2 is complete has already run.", codeafter2run[0]); + didRun2[0] = true; + nd.next(); + return ; + } + }; + m.Use(new AnonymousReceiveMiddleware(mwc2)); + + m.ReceiveActivity(null); + Assert.assertTrue(didRun1[0]); + Assert.assertTrue(didRun2[0]); + Assert.assertTrue(codeafter2run[0]); + } + + @Test + public void CatchAnExceptionViaMiddlware() throws Exception { + MiddlewareSet m = new MiddlewareSet(); + final boolean caughtException[] = {false}; + + MiddlewareCall mwc1 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws ExecutionException, InterruptedException { + try { + nd.next(); + Assert.assertTrue("Should not get here", false); + + } + catch (InterruptedException ex) { + System.out.println("Here isi the exception message" + ex.getMessage()); + System.out.flush(); + Assert.assertTrue(ex.getMessage() == "test"); + + caughtException[0] = true; + } catch (Exception e) { + Assert.assertTrue("Should not get here" + e.getMessage(), false); + } + return ; + }}; + + m.Use(new AnonymousReceiveMiddleware(mwc1)); + + MiddlewareCall mwc2 = new MiddlewareCall() { + public void requestHandler(TurnContext tc, NextDelegate nd) throws InterruptedException { + throw new InterruptedException("test"); + } + }; + + m.Use(new AnonymousReceiveMiddleware(mwc2)); + + m.ReceiveActivity(null); + Assert.assertTrue(caughtException[0]); + } + + + +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java index 7c5cca1e2..8c52d36a7 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java @@ -2,22 +2,18 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. */ package com.microsoft.bot.connector; import com.microsoft.bot.schema.models.AttachmentInfo; -import com.microsoft.bot.connector.models.ErrorResponseException; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; -import java.io.InputStream; import rx.Observable; +import java.io.InputStream; + /** * An instance of this class provides access to all the operations defined * in Attachments. @@ -28,10 +24,9 @@ public interface Attachments { * Get AttachmentInfo structure describing the attachment views. * * @param attachmentId attachment id - * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server - * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the AttachmentInfo object if successful. + * @throws IllegalArgumentException thrown if parameters fail the validation + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent */ AttachmentInfo getAttachmentInfo(String attachmentId); @@ -39,10 +34,10 @@ public interface Attachments { * GetAttachmentInfo. * Get AttachmentInfo structure describing the attachment views. * - * @param attachmentId attachment id + * @param attachmentId attachment id * @param serviceCallback the async ServiceCallback to handle successful and failed responses. - * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object + * @throws IllegalArgumentException thrown if parameters fail the validation */ ServiceFuture getAttachmentInfoAsync(String attachmentId, final ServiceCallback serviceCallback); @@ -51,8 +46,8 @@ public interface Attachments { * Get AttachmentInfo structure describing the attachment views. * * @param attachmentId attachment id - * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the AttachmentInfo object + * @throws IllegalArgumentException thrown if parameters fail the validation */ Observable getAttachmentInfoAsync(String attachmentId); @@ -61,8 +56,8 @@ public interface Attachments { * Get AttachmentInfo structure describing the attachment views. * * @param attachmentId attachment id - * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the AttachmentInfo object + * @throws IllegalArgumentException thrown if parameters fail the validation */ Observable> getAttachmentInfoWithServiceResponseAsync(String attachmentId); @@ -71,11 +66,10 @@ public interface Attachments { * Get the named view as binary content. * * @param attachmentId attachment id - * @param viewId View id from attachmentInfo - * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server - * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent + * @param viewId View id from attachmentInfo * @return the InputStream object if successful. + * @throws IllegalArgumentException thrown if parameters fail the validation + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent */ InputStream getAttachment(String attachmentId, String viewId); @@ -83,11 +77,11 @@ public interface Attachments { * GetAttachment. * Get the named view as binary content. * - * @param attachmentId attachment id - * @param viewId View id from attachmentInfo + * @param attachmentId attachment id + * @param viewId View id from attachmentInfo * @param serviceCallback the async ServiceCallback to handle successful and failed responses. - * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object + * @throws IllegalArgumentException thrown if parameters fail the validation */ ServiceFuture getAttachmentAsync(String attachmentId, String viewId, final ServiceCallback serviceCallback); @@ -96,9 +90,9 @@ public interface Attachments { * Get the named view as binary content. * * @param attachmentId attachment id - * @param viewId View id from attachmentInfo - * @throws IllegalArgumentException thrown if parameters fail the validation + * @param viewId View id from attachmentInfo * @return the observable to the InputStream object + * @throws IllegalArgumentException thrown if parameters fail the validation */ Observable getAttachmentAsync(String attachmentId, String viewId); @@ -107,9 +101,9 @@ public interface Attachments { * Get the named view as binary content. * * @param attachmentId attachment id - * @param viewId View id from attachmentInfo - * @throws IllegalArgumentException thrown if parameters fail the validation + * @param viewId View id from attachmentInfo * @return the observable to the InputStream object + * @throws IllegalArgumentException thrown if parameters fail the validation */ Observable> getAttachmentWithServiceResponseAsync(String attachmentId, String viewId); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Channels.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Channels.java new file mode 100644 index 000000000..3b7a2e4ee --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Channels.java @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +public class Channels { + /** + * Console channel. + */ + public static final String CONSOLE = "console"; + + /** + * Cortana channel. + */ + public static final String CORTANA = "cortana"; + + /** + * Direct Line channel. + */ + public static final String DIRECTLINE = "directline"; + + /** + * Email channel. + */ + public static final String EMAIL = "email"; + + /** + * Emulator channel. + */ + public static final String EMULATOR = "emulator"; + + /** + * Facebook channel. + */ + public static final String FACEBOOK = "facebook"; + + /** + * Group Me channel. + */ + public static final String GROUPME = "groupme"; + + /** + * Kik channel. + */ + public static final String KIK = "kik"; + + /** + * Line channel. + */ + public static final String LINE = "line"; + + /** + * MS Teams channel. + */ + public static final String MSTEAMS = "msteams"; + + /** + * Skype channel. + */ + public static final String SKYPE = "skype"; + + /** + * Skype for Business channel. + */ + public static final String SKYPEFORBUSINESS = "skypeforbusiness"; + + /** + * Slack channel. + */ + public static final String SLACK = "slack"; + + /** + * SMS (Twilio) channel. + */ + public static final String SMS = "sms"; + + /** + * Telegram channel. + */ + public static final String TELEGRAM = "telegram"; + + /** + * WebChat channel. + */ + public static final String WEBCHAT = "webchat"; + + /** + * Test channel. + */ + public static final String TEST = "test"; +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java index a1d509585..fa7b9b5cb 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * + *

* Code generated by Microsoft (R) AutoRest Code Generator. * Changes may cause incorrect behavior and will be lost if the code is * regenerated. @@ -21,7 +21,7 @@ public interface ConnectorClient { * Gets the REST client. * * @return the {@link RestClient} object. - */ + */ RestClient restClient(); /** diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClientFuture.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClientFuture.java deleted file mode 100644 index cc5ab5194..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClientFuture.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.microsoft.bot.connector; - -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.rest.RestClient; -import com.microsoft.rest.credentials.ServiceClientCredentials; - -public class ConnectorClientFuture extends ConnectorClientImpl { - - /** - * Initializes an instance of ConnectorClient client. - * - * @param credentials the management credentials for Azure - */ - public ConnectorClientFuture(ServiceClientCredentials credentials) { - super(credentials); - } - - /** - * Initializes an instance of ConnectorClient client. - * - * @param baseUrl the base URL of the host - * @param credentials the management credentials for Azure - */ - public ConnectorClientFuture(String baseUrl, ServiceClientCredentials credentials) { - super(baseUrl, credentials); - } - - /** - * Initializes an instance of ConnectorClient client. - * - * @param restClient the REST client to connect to Azure. - */ - public ConnectorClientFuture(RestClient restClient) { - super(restClient); - } - - @Override - public String userAgent() { - return "Microsoft-BotFramework/4.0"; - } -} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java index 6c7ebd424..a07381758 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * + *

* Code generated by Microsoft (R) AutoRest Code Generator. * Changes may cause incorrect behavior and will be lost if the code is * regenerated. @@ -10,22 +10,14 @@ package com.microsoft.bot.connector; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.AttachmentData; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ConversationParameters; -import com.microsoft.bot.schema.models.ConversationResourceResponse; -import com.microsoft.bot.schema.models.ConversationsResult; -import com.microsoft.bot.schema.models.PagedMembersResult; -import com.microsoft.bot.connector.models.ErrorResponseException; -import com.microsoft.bot.schema.models.ResourceResponse; -import com.microsoft.bot.schema.models.Transcript; +import com.microsoft.bot.schema.models.*; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; -import java.util.List; import rx.Observable; +import java.util.List; + /** * An instance of this class provides access to all the operations defined * in Conversations. @@ -40,7 +32,6 @@ public interface Conversations { Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. * * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ConversationsResult object if successful. */ @@ -85,6 +76,7 @@ public interface Conversations { * @return the observable to the ConversationsResult object */ Observable> getConversationsWithServiceResponseAsync(); + /** * GetConversations. * List the Conversations in which this bot has participated. @@ -95,7 +87,6 @@ public interface Conversations { * * @param continuationToken skip or continuation token * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ConversationsResult object if successful. */ @@ -161,7 +152,6 @@ public interface Conversations { * * @param parameters Parameters to create the conversation from * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ConversationResourceResponse object if successful. */ @@ -243,7 +233,6 @@ This is slightly different from ReplyToActivity(). * @param conversationId Conversation ID * @param activity Activity to send * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -308,7 +297,6 @@ This is slightly different from ReplyToActivity(). * @param activityId activityId to update * @param activity replacement Activity * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -370,7 +358,6 @@ This is slightly different from SendToConversation(). * @param activityId activityId the reply is to (OPTIONAL) * @param activity Activity to send * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -436,7 +423,6 @@ This is slightly different from SendToConversation(). * @param conversationId Conversation ID * @param activityId activityId to delete * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent */ void deleteActivity(String conversationId, String activityId); @@ -485,7 +471,6 @@ This is slightly different from SendToConversation(). * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the List<ChannelAccount> object if successful. */ @@ -534,7 +519,6 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @param conversationId Conversation ID * @param memberId ID of the member to delete from this conversation * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent */ void deleteConversationMember(String conversationId, String memberId); @@ -587,7 +571,6 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @param conversationId Conversation ID * @param activityId Activity ID * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the List<ChannelAccount> object if successful. */ @@ -639,7 +622,6 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @param conversationId Conversation ID * @param attachmentUpload Attachment data * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -688,15 +670,14 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * This method allows you to upload the historic activities to the conversation. - * - * Sender must ensure that the historic activities have unique ids and appropriate timestamps. - * The ids are used by the client to deal with duplicate activities and the timestamps are used by + * + * Sender must ensure that the historic activities have unique ids and appropriate timestamps. + * The ids are used by the client to deal with duplicate activities and the timestamps are used by * the client to render the activities in the right order. * * @param conversationId Conversation ID * @param history Historic activities * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -704,16 +685,15 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * This method allows you to upload the historic activities to the conversation. - * - * Sender must ensure that the historic activities have unique ids and appropriate timestamps. - * The ids are used by the client to deal with duplicate activities and the timestamps are used by + * + * Sender must ensure that the historic activities have unique ids and appropriate timestamps. + * The ids are used by the client to deal with duplicate activities and the timestamps are used by * the client to render the activities in the right order. * * @param conversationId Conversation ID * @param history Historic activities * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -721,15 +701,14 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * This method allows you to upload the historic activities to the conversation. - * - * Sender must ensure that the historic activities have unique ids and appropriate timestamps. - * The ids are used by the client to deal with duplicate activities and the timestamps are used by + * + * Sender must ensure that the historic activities have unique ids and appropriate timestamps. + * The ids are used by the client to deal with duplicate activities and the timestamps are used by * the client to render the activities in the right order. * * @param conversationId Conversation ID * @param history Historic activities * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ @@ -737,38 +716,36 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * This method allows you to upload the historic activities to the conversation. - * - * Sender must ensure that the historic activities have unique ids and appropriate timestamps. - * The ids are used by the client to deal with duplicate activities and the timestamps are used by + * + * Sender must ensure that the historic activities have unique ids and appropriate timestamps. + * The ids are used by the client to deal with duplicate activities and the timestamps are used by * the client to render the activities in the right order. * * @param conversationId Conversation ID * @param history Historic activities * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ - Observable> sendConversationHistoryWithServiceResponseAsync(String conversationId, Transcript history); + Observable> sendConversationHistoryWithServiceResponseAsync(String conversationId, Transcript history); /** * Enumerate the members of a conversation one page at a time. - * - * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. - * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members + * + * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. + * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members * of the conversation and a continuation token that can be used to get more values. - * - * One page of ChannelAccounts records are returned with each call. The number of records in a page may - * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no - * additional results the response will not contain a continuation token. If there are no members in the + * + * One page of ChannelAccounts records are returned with each call. The number of records in a page may + * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no + * additional results the response will not contain a continuation token. If there are no members in the * conversation the Members will be empty or not present in the response. - * - * A response to a request that has a continuation token from a prior request may rarely return members + * + * A response to a request that has a continuation token from a prior request may rarely return members * from a previous request. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the PagedMembersResult object if successful. */ @@ -776,23 +753,22 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * Enumerate the members of a conversation one page at a time. - * - * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. - * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members + * + * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. + * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members * of the conversation and a continuation token that can be used to get more values. - * - * One page of ChannelAccounts records are returned with each call. The number of records in a page may - * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no - * additional results the response will not contain a continuation token. If there are no members in the + * + * One page of ChannelAccounts records are returned with each call. The number of records in a page may + * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no + * additional results the response will not contain a continuation token. If there are no members in the * conversation the Members will be empty or not present in the response. - * - * A response to a request that has a continuation token from a prior request may rarely return members + * + * A response to a request that has a continuation token from a prior request may rarely return members * from a previous request. * * @param conversationId Conversation ID * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the PagedMembersResult object if successful. */ @@ -800,22 +776,21 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * Enumerate the members of a conversation one page at a time. - * - * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. - * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members + * + * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. + * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members * of the conversation and a continuation token that can be used to get more values. - * - * One page of ChannelAccounts records are returned with each call. The number of records in a page may - * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no - * additional results the response will not contain a continuation token. If there are no members in the + * + * One page of ChannelAccounts records are returned with each call. The number of records in a page may + * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no + * additional results the response will not contain a continuation token. If there are no members in the * conversation the Members will be empty or not present in the response. - * - * A response to a request that has a continuation token from a prior request may rarely return members + * + * A response to a request that has a continuation token from a prior request may rarely return members * from a previous request. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the PagedMembersResult object if successful. */ @@ -823,25 +798,24 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * Enumerate the members of a conversation one page at a time. - * - * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. - * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members + * + * This REST API takes a ConversationId. Optionally a pageSize and/or continuationToken can be provided. + * It returns a PagedMembersResult, which contains an array of ChannelAccounts representing the members * of the conversation and a continuation token that can be used to get more values. - * - * One page of ChannelAccounts records are returned with each call. The number of records in a page may - * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no - * additional results the response will not contain a continuation token. If there are no members in the + * + * One page of ChannelAccounts records are returned with each call. The number of records in a page may + * vary between channels and calls. The pageSize parameter can be used as a suggestion. If there are no + * additional results the response will not contain a continuation token. If there are no members in the * conversation the Members will be empty or not present in the response. - * - * A response to a request that has a continuation token from a prior request may rarely return members + * + * A response to a request that has a continuation token from a prior request may rarely return members * from a previous request. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation - * @throws ErrorResponseException thrown if the request is rejected by server * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the observable to the ResourceResponse object */ Observable> getConversationPagedMembersWithServiceResponseAsync(String conversationId); - } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java index 68c5742f3..9783ffa43 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java @@ -4,7 +4,6 @@ package com.microsoft.bot.connector; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; @@ -23,13 +22,13 @@ public ForkJoinWorkerThread newThread(ForkJoinPool pool) { } }; - private static ExecutorService executor= new ForkJoinPool( + private static ExecutorService executor = new ForkJoinPool( Runtime.getRuntime().availableProcessors() * 2, factory, null, false); - public static ExecutorService getExecutor(){ + public static ExecutorService getExecutor() { return executor; } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java index 84febd4db..efc985190 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java @@ -1,6 +1,6 @@ package com.microsoft.bot.connector; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; import java.io.IOException; import java.io.InputStream; @@ -23,7 +23,7 @@ public class UserAgent { String build_version; final Properties properties = new Properties(); try { - InputStream propStream = ConnectorClientImpl.class.getClassLoader().getResourceAsStream("project.properties"); + InputStream propStream = RestConnectorClient.class.getClassLoader().getResourceAsStream("project.properties"); properties.load(propStream); build_version = properties.getProperty("version"); } catch (IOException e) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java index 0e07140c1..82c763a63 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java @@ -23,7 +23,7 @@ public AdalAuthenticator(ClientCredential clientCredential, OAuthConfiguration c this.context = new AuthenticationContext(configurationOAuth.authority(), false, ExecutorFactory.getExecutor()); } - public Future acquireToken(){ + public Future acquireToken() { return context.acquireToken(oAuthConfiguration.scope(), clientCredential, null); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConfiguration.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConfiguration.java new file mode 100644 index 000000000..33a5bce57 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConfiguration.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +import java.util.ArrayList; +import java.util.List; + +/** + * General configuration settings for authentication. + */ +public class AuthenticationConfiguration { + public List requiredEndorsements() { + return new ArrayList(); + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java index e1b4b307a..f83fadbc4 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java @@ -11,39 +11,39 @@ public final class AuthenticationConstants { * TO CHANNEL FROM BOT: Login URL. */ @Deprecated - public static final String ToChannelFromBotLoginUrl = "https://login.microsoftonline.com/botframework.com"; + public static final String TO_CHANNEL_FROM_BOT_LOGIN_URL = "https://login.microsoftonline.com/botframework.com"; /** * TO CHANNEL FROM BOT: Login URL template string. Bot developer may specify * which tenant to obtain an access token from. By default, the channels only * accept tokens from "botframework.com". For more details see https://aka.ms/bots/tenant-restriction. */ - public static final String ToChannelFromBotLoginUrlTemplate = "https://login.microsoftonline.com/%s"; + public static final String TO_CHANNEL_FROM_BOT_LOGIN_URL_TEMPLATE = "https://login.microsoftonline.com/%s"; /** * TO CHANNEL FROM BOT: OAuth scope to request. */ - public static final String ToChannelFromBotOAuthScope = "https://api.botframework.com"; + public static final String TO_CHANNEL_FROM_BOT_OAUTH_SCOPE = "https://api.botframework.com"; /** * TO BOT FROM CHANNEL: Token issuer. */ - public static final String ToBotFromChannelTokenIssuer = "https://api.botframework.com"; + public static final String TO_BOT_FROM_CHANNEL_TOKEN_ISSUER = "https://api.botframework.com"; /** * TO BOT FROM CHANNEL: OpenID metadata document for tokens coming from MSA. */ - public static final String ToBotFromChannelOpenIdMetadataUrl = "https://login.botframework.com/v1/.well-known/openidconfiguration"; + public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = "https://login.botframework.com/v1/.well-known/openidconfiguration"; /** * TO BOT FROM EMULATOR: OpenID metadata document for tokens coming from MSA. */ - public static final String ToBotFromEmulatorOpenIdMetadataUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; + public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; /** * TO BOT FROM ENTERPRISE CHANNEL: OpenID metadata document for tokens coming from MSA. */ - public static final String ToBotFromEnterpriseChannelOpenIdMetadataUrlFormat = "https://%s.enterprisechannel.botframework.com/v1/.well-known/openidconfiguration"; + public static final String TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT = "https://%s.enterprisechannel.botframework.com/v1/.well-known/openidconfiguration"; /** * Allowed token signing algorithms. Tokens come from channels to the bot. The code @@ -54,27 +54,27 @@ public final class AuthenticationConstants { /** * Application Setting Key for the OAuthUrl value. */ - public static final String OAuthUrlKey = "OAuthApiEndpoint"; + public static final String OAUTH_URL_KEY = "OAuthApiEndpoint"; /** * OAuth Url used to get a token from OAuthApiClient. */ - public static final String OAuthUrl = "https://api.botframework.com"; + public static final String OAUTH_URL = "https://api.botframework.com"; /** * Application Settings Key for whether to emulate OAuthCards when using the emulator. */ - public static final String EmulateOAuthCardsKey = "EmulateOAuthCards"; + public static final String EMULATE_OAUTH_CARDS_KEY = "EmulateOAuthCards"; /** * Application Setting Key for the OpenIdMetadataUrl value. */ - public static final String BotOpenIdMetadataKey = "BotOpenIdMetadata"; + public static final String BOT_OPENID_METADATA_KEY = "BotOpenIdMetadata"; /** * The default tenant to acquire bot to channel token from. */ - public static final String DefaultChannelAuthTenant = "botframework.com"; + public static final String DEFAULT_CHANNEL_AUTH_TENANT = "botframework.com"; /** * "azp" Claim. @@ -82,7 +82,7 @@ public final class AuthenticationConstants { * This claim follows the general format set forth in the OpenID Spec. * http://openid.net/specs/openid-connect-core-1_0.html#IDToken. */ - public static final String AuthorizedParty = "azp"; + public static final String AUTHORIZED_PARTY = "azp"; /** * Audience Claim. From RFC 7519. @@ -99,7 +99,7 @@ public final class AuthenticationConstants { * interpretation of audience values is generally application specific. * Use of this claim is OPTIONAL. */ - public static final String AudienceClaim = "aud"; + public static final String AUDIENCE_CLAIM = "aud"; /** * From RFC 7515 @@ -112,22 +112,22 @@ public final class AuthenticationConstants { * When used with a JWK, the "kid" value is used to match a JWK "kid" * parameter value. */ - public static final String KeyIdHeader = "kid"; + public static final String KEY_ID_HEADER = "kid"; /** * Service URL claim name. As used in Microsoft Bot Framework v3.1 auth. */ - public static final String ServiceUrlClaim = "serviceurl"; + public static final String SERVICE_URL_CLAIM = "serviceurl"; /** * Token version claim name. As used in Microsoft AAD tokens. */ - public static final String VersionClaim = "ver"; + public static final String VERSION_CLAIM = "ver"; /** * App ID claim name. As used in Microsoft AAD 1.0 tokens. */ - public static final String AppIdClaim = "appid"; + public static final String APPID_CLAIM = "appid"; static { AllowedSigningAlgorithms.add("RS256"); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/BotCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/BotCredentials.java deleted file mode 100644 index 96666f997..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/BotCredentials.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.connector.authentication; - -public class BotCredentials { - protected String appId; - protected String appPassword; - - public String appId() { return this.appId; } - - public String appPassword() { return this.appPassword; } - - public BotCredentials withAppId(String appId) { - this.appId = appId; - return this; - } - - public BotCredentials withAppPassword(String appPassword) { - this.appPassword = appPassword; - return this; - } -} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelProvider.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelProvider.java new file mode 100644 index 000000000..eabde8899 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelProvider.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +import java.util.concurrent.CompletableFuture; + +/** + * ChannelProvider interface. This interface allows Bots to provide their own + * implementation for the configuration parameters to connect to a Bot. + * Framework channel service. + */ +public interface ChannelProvider { + /** + * Gets the channel service property for this channel provider. + * + * @return The channel service property for the channel provider. + */ + CompletableFuture getChannelService(); + + /** + * Gets a value of whether this provider represents a channel on Government Azure. + * + * @return True if this channel provider represents a channel on Government Azure. + */ + boolean isGovernment(); + + /** + * Gets a value of whether this provider represents a channel on Public Azure. + * + * @return True if this channel provider represents a channel on Public Azure. + */ + boolean isPublicAzure(); +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index 0bd10c642..1540f75d7 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -4,6 +4,7 @@ package com.microsoft.bot.connector.authentication; import com.microsoft.aad.adal4j.AuthenticationException; +import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -16,76 +17,104 @@ public class ChannelValidation { /** * Validate the incoming Auth Header as a token sent from the Bot Framework Service. - * @param authHeader The raw HTTP header in the format: "Bearer [longString]" + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]" * @param credentials The user defined set of valid credentials, such as the AppId. - * @param channelId ChannelId for endorsements validation. + * @param channelId ChannelId for endorsements validation. * @return A valid ClaimsIdentity. * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + return authenticateToken(authHeader, credentials, channelId, new AuthenticationConfiguration()); + } + + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( ToBotFromChannelTokenValidationParameters, - AuthenticationConstants.ToBotFromChannelOpenIdMetadataUrl, + AuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, AuthenticationConstants.AllowedSigningAlgorithms); - ClaimsIdentity identity = tokenExtractor.getIdentityAsync(authHeader, channelId).get(); - if (identity == null) { - // No valid identity. Not Authorized. - throw new AuthenticationException("Invalid Identity"); - } - - if (!identity.isAuthenticated()) { - // The token is in some way invalid. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); - } - - // Now check that the AppID in the claims set matches - // what we're looking for. Note that in a multi-tenant bot, this value - // comes from developer code that may be reaching out to a service, hence the - // Async validation. - - // Look for the "aud" claim, but only if issued from the Bot Framework - if (!identity.getIssuer().equalsIgnoreCase(AuthenticationConstants.ToBotFromChannelTokenIssuer)) { - throw new AuthenticationException("Token Not Authenticated"); - } - - // The AppId from the claim in the token must match the AppId specified by the developer. Note that - // the Bot Framework uses the Audience claim ("aud") to pass the AppID. - String appIdFromClaim = identity.claims().get(AuthenticationConstants.AudienceClaim); - if (appIdFromClaim == null || appIdFromClaim.isEmpty()) { - // Claim is present, but doesn't have a value. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); - } - - if (!credentials.isValidAppIdAsync(appIdFromClaim).get()) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); - } - - return CompletableFuture.completedFuture(identity); + return tokenExtractor.getIdentityAsync(authHeader, channelId) + .thenApply(identity -> { + if (identity == null) { + // No valid identity. Not Authorized. + throw new AuthenticationException("Invalid Identity"); + } + + if (!identity.isAuthenticated()) { + // The token is in some way invalid. Not Authorized. + throw new AuthenticationException("Token Not Authenticated"); + } + + // Now check that the AppID in the claims set matches + // what we're looking for. Note that in a multi-tenant bot, this value + // comes from developer code that may be reaching out to a service, hence the + // Async validation. + + // Look for the "aud" claim, but only if issued from the Bot Framework + if (!identity.getIssuer().equalsIgnoreCase(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER)) { + throw new AuthenticationException("Token Not Authenticated"); + } + + return identity; + }) + + .thenApply(identity -> { + // The AppId from the claim in the token must match the AppId specified by the developer. Note that + // the Bot Framework uses the Audience claim ("aud") to pass the AppID. + String appIdFromClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromClaim)) { + // Claim is present, but doesn't have a value. Not Authorized. + throw new AuthenticationException("Token Not Authenticated"); + } + + if (!credentials.isValidAppIdAsync(appIdFromClaim).join()) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); + } + + return identity; + }); } /** * Validate the incoming Auth Header as a token sent from the Bot Framework Service. - * @param authHeader The raw HTTP header in the format: "Bearer [longString]" + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]" * @param credentials The user defined set of valid credentials, such as the AppId. - * @param channelId ChannelId for endorsements validation. - * @param serviceUrl Service url. + * @param channelId ChannelId for endorsements validation. + * @param serviceUrl Service url. * @return A valid ClaimsIdentity. * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader,CredentialProvider credentials, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { - ClaimsIdentity identity = ChannelValidation.authenticateToken(authHeader, credentials, channelId).get(); - - if (!identity.claims().containsKey(AuthenticationConstants.ServiceUrlClaim)) { - // Claim must be present. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Channel Token.", AuthenticationConstants.ServiceUrlClaim)); - } - - if (!serviceUrl.equalsIgnoreCase(identity.claims().get(AuthenticationConstants.ServiceUrlClaim))) { - // Claim must match. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim does not match service url provided (%s).", AuthenticationConstants.ServiceUrlClaim, serviceUrl)); - } + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { + return authenticateToken(authHeader, credentials, channelId, serviceUrl, new AuthenticationConfiguration()); + } - return CompletableFuture.completedFuture(identity); + /** + * Validate the incoming Auth Header as a token sent from the Bot Framework Service. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]" + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelId ChannelId for endorsements validation. + * @param serviceUrl Service url. + * @param authConfig The authentication configuration. + * @return A valid ClaimsIdentity. + * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + return ChannelValidation.authenticateToken(authHeader, credentials, channelId, authConfig) + .thenApply(identity -> { + if (!identity.claims().containsKey(AuthenticationConstants.SERVICE_URL_CLAIM)) { + // Claim must be present. Not Authorized. + throw new AuthenticationException(String.format("'%s' claim is required on Channel Token.", AuthenticationConstants.SERVICE_URL_CLAIM)); + } + + if (!serviceUrl.equalsIgnoreCase(identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM))) { + // Claim must match. Not Authorized. + throw new AuthenticationException(String.format("'%s' claim does not match service url provided (%s).", AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl)); + } + + return identity; + }); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentity.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentity.java index d7aa764a1..1bb46948c 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentity.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentity.java @@ -3,10 +3,45 @@ package com.microsoft.bot.connector.authentication; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.HashMap; import java.util.Map; -public interface ClaimsIdentity { - boolean isAuthenticated(); - Map claims(); - String getIssuer(); +public class ClaimsIdentity { + private String issuer; + private Map claims; + + private ClaimsIdentity() { + this("", new HashMap<>()); + } + + public ClaimsIdentity(String authIssuer) { + this(authIssuer, new HashMap<>()); + } + + public ClaimsIdentity(String authIssuer, Map claims) { + this.issuer = authIssuer; + this.claims = claims; + } + + public ClaimsIdentity(DecodedJWT jwt) { + claims = new HashMap<>(); + if (jwt.getClaims() != null) { + jwt.getClaims().forEach((k, v) -> claims.put(k, v.asString())); + } + issuer = jwt.getIssuer(); + } + + public boolean isAuthenticated() { + return this.issuer != null && !this.issuer.isEmpty(); + } + + public Map claims() { + return this.claims; + } + + public String getIssuer() { + return issuer; + } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentityImpl.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentityImpl.java deleted file mode 100644 index 1b7f66d84..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ClaimsIdentityImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.connector.authentication; - -import java.util.HashMap; -import java.util.Map; - -public class ClaimsIdentityImpl implements ClaimsIdentity { - private String issuer; - private Map claims; - - public ClaimsIdentityImpl() { - this("", new HashMap<>()); - } - - public ClaimsIdentityImpl(String authType) { - this(authType, new HashMap<>()); - } - - public ClaimsIdentityImpl(String authType, Map claims) { - this.issuer = authType; - this.claims = claims; - } - - @Override - public boolean isAuthenticated() { - return this.issuer != null && !this.issuer.isEmpty(); - } - - @Override - public Map claims() { - return this.claims; - } - - @Override - public String getIssuer() { - return issuer; - } -} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProviderImpl.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProviderImpl.java deleted file mode 100644 index 779216470..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProviderImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.connector.authentication; - -import java.util.concurrent.CompletableFuture; - -public class CredentialProviderImpl extends BotCredentials implements CredentialProvider { - - public CredentialProviderImpl(String appId, String appPassword) { - this.appId = appId; - this.appPassword = appPassword; - } - - public CredentialProviderImpl(BotCredentials credentials) { - this(credentials.appId, credentials.appPassword); - } - - @Override - public CredentialProviderImpl withAppId(String appId) { - return (CredentialProviderImpl) super.withAppId(appId); - } - - @Override - public CredentialProviderImpl withAppPassword(String appPassword) { - return (CredentialProviderImpl) super.withAppPassword(appPassword); - } - - @Override - public CompletableFuture isValidAppIdAsync(String appId) { - return CompletableFuture.completedFuture(this.appId.equals(appId)); - } - - @Override - public CompletableFuture getAppPasswordAsync(String appId) { - return CompletableFuture.completedFuture(this.appId.equals(appId) ? this.appPassword : null); - } - - @Override - public CompletableFuture isAuthenticationDisabledAsync() { - return CompletableFuture.completedFuture(this.appId == null || this.appId.isEmpty()); - } -} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index c63842f86..7e7aaac77 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -6,6 +6,7 @@ import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.DecodedJWT; import com.microsoft.aad.adal4j.AuthenticationException; +import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -17,25 +18,26 @@ public class EmulatorValidation { /** * TO BOT FROM EMULATOR: Token validation parameters when connecting to a channel. */ - public static final TokenValidationParameters ToBotFromEmulatorTokenValidationParameters = TokenValidationParameters.toBotFromEmulatorTokenValidationParameters(); + private static final TokenValidationParameters ToBotFromEmulatorTokenValidationParameters = TokenValidationParameters.toBotFromEmulatorTokenValidationParameters(); /** * Determines if a given Auth header is from the Bot Framework Emulator + * * @param authHeader Bearer Token, in the "Bearer [Long String]" Format. * @return True, if the token was issued by the Emulator. Otherwise, false. */ - public static CompletableFuture isTokenFromEmulator(String authHeader) { + public static Boolean isTokenFromEmulator(String authHeader) { // The Auth Header generally looks like this: // "Bearer eyJ0e[...Big Long String...]XAiO" - if (authHeader == null || authHeader.isEmpty()) { + if (StringUtils.isEmpty(authHeader)) { // No token. Can't be an emulator token. - return CompletableFuture.completedFuture(false); + return false; } String[] parts = authHeader.split(" "); if (parts.length != 2) { // Emulator tokens MUST have exactly 2 parts. If we don't have 2 parts, it's not an emulator token - return CompletableFuture.completedFuture(false); + return false; } String schema = parts[0]; @@ -43,7 +45,7 @@ public static CompletableFuture isTokenFromEmulator(String authHeader) if (!schema.equalsIgnoreCase("bearer")) { // The scheme from the emulator MUST be "Bearer" - return CompletableFuture.completedFuture(false); + return false; } // Parse the Big Long String into an actual token. @@ -52,82 +54,103 @@ public static CompletableFuture isTokenFromEmulator(String authHeader) // Is there an Issuer? if (decodedJWT.getIssuer().isEmpty()) { // No Issuer, means it's not from the Emulator. - return CompletableFuture.completedFuture(false); + return false; } // Is the token issues by a source we consider to be the emulator? - if (!ToBotFromEmulatorTokenValidationParameters.validIssuers.contains(decodedJWT.getIssuer())) { - // Not a Valid Issuer. This is NOT a Bot Framework Emulator Token. - return CompletableFuture.completedFuture(false); - } - - // The Token is from the Bot Framework Emulator. Success! - return CompletableFuture.completedFuture(true); + // Not a Valid Issuer. This is NOT a Bot Framework Emulator Token. + return ToBotFromEmulatorTokenValidationParameters.validIssuers.contains(decodedJWT.getIssuer()); } /** * Validate the incoming Auth Header as a token sent from the Bot Framework Emulator. - * @param authHeader The raw HTTP header in the format: "Bearer [longString]" - * @param credentials The user defined set of valid credentials, such as the AppId. + * A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. + * @param channelId The ID of the channel to validate. * @return A valid ClaimsIdentity. * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { - JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( - ToBotFromEmulatorTokenValidationParameters, - AuthenticationConstants.ToBotFromEmulatorOpenIdMetadataUrl, - AuthenticationConstants.AllowedSigningAlgorithms); - - ClaimsIdentity identity = tokenExtractor.getIdentityAsync(authHeader, channelId).get(); - if (identity == null) { - // No valid identity. Not Authorized. - throw new AuthenticationException("Invalid Identity"); - } - - if (!identity.isAuthenticated()) { - // The token is in some way invalid. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); - } - - // Now check that the AppID in the claims set matches - // what we're looking for. Note that in a multi-tenant bot, this value - // comes from developer code that may be reaching out to a service, hence the - // Async validation. - if (!identity.claims().containsKey(AuthenticationConstants.VersionClaim)) { - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Tokens.", AuthenticationConstants.VersionClaim)); - } - - String tokenVersion = identity.claims().get(AuthenticationConstants.VersionClaim); - String appId = ""; - - // The Emulator, depending on Version, sends the AppId via either the - // appid claim (Version 1) or the Authorized Party claim (Version 2). - if (tokenVersion.isEmpty() || tokenVersion.equalsIgnoreCase("1.0")) { - // either no Version or a version of "1.0" means we should look for - // the claim in the "appid" claim. - if (!identity.claims().containsKey(AuthenticationConstants.AppIdClaim)) { - // No claim around AppID. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '1.0'.", AuthenticationConstants.AppIdClaim)); - } - - appId = identity.claims().get(AuthenticationConstants.AppIdClaim); - } else if (tokenVersion.equalsIgnoreCase("2.0")) { - // Emulator, "2.0" puts the AppId in the "azp" claim. - if (!identity.claims().containsKey(AuthenticationConstants.AuthorizedParty)) { - // No claim around AppID. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '2.0'.", AuthenticationConstants.AuthorizedParty)); - } - - appId = identity.claims().get(AuthenticationConstants.AuthorizedParty); - } else { - // Unknown Version. Not Authorized. - throw new AuthenticationException(String.format("Unknown Emulator Token version '%s'.", tokenVersion)); - } + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + return authenticateToken(authHeader, credentials, channelProvider, channelId, new AuthenticationConfiguration()); + } - if (!credentials.isValidAppIdAsync(appId).get()) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appId)); - } + /** + * Validate the incoming Auth Header as a token sent from the Bot Framework Emulator. + * A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. + * @param channelId The ID of the channel to validate. + * @param authConfig The authentication configuration. + * @return A valid ClaimsIdentity. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + String openIdMetadataUrl = channelProvider != null && channelProvider.isGovernment() ? + GovernmentAuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL : + AuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL; - return CompletableFuture.completedFuture(identity); + JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( + ToBotFromEmulatorTokenValidationParameters, + openIdMetadataUrl, + AuthenticationConstants.AllowedSigningAlgorithms); + + return tokenExtractor.getIdentityAsync(authHeader, channelId, authConfig.requiredEndorsements()) + .thenApply(identity -> { + if (identity == null) { + // No valid identity. Not Authorized. + throw new AuthenticationException("Invalid Identity"); + } + + if (!identity.isAuthenticated()) { + // The token is in some way invalid. Not Authorized. + throw new AuthenticationException("Token Not Authenticated"); + } + + // Now check that the AppID in the claims set matches + // what we're looking for. Note that in a multi-tenant bot, this value + // comes from developer code that may be reaching out to a service, hence the + // Async validation. + if (!identity.claims().containsKey(AuthenticationConstants.VERSION_CLAIM)) { + throw new AuthenticationException(String.format("'%s' claim is required on Emulator Tokens.", AuthenticationConstants.VERSION_CLAIM)); + } + + String tokenVersion = identity.claims().get(AuthenticationConstants.VERSION_CLAIM); + String appId = ""; + + // The Emulator, depending on Version, sends the AppId via either the + // appid claim (Version 1) or the Authorized Party claim (Version 2). + if (tokenVersion.isEmpty() || tokenVersion.equalsIgnoreCase("1.0")) { + // either no Version or a version of "1.0" means we should look for + // the claim in the "appid" claim. + if (!identity.claims().containsKey(AuthenticationConstants.APPID_CLAIM)) { + // No claim around AppID. Not Authorized. + throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '1.0'.", AuthenticationConstants.APPID_CLAIM)); + } + + appId = identity.claims().get(AuthenticationConstants.APPID_CLAIM); + } else if (tokenVersion.equalsIgnoreCase("2.0")) { + // Emulator, "2.0" puts the AppId in the "azp" claim. + if (!identity.claims().containsKey(AuthenticationConstants.AUTHORIZED_PARTY)) { + // No claim around AppID. Not Authorized. + throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '2.0'.", AuthenticationConstants.AUTHORIZED_PARTY)); + } + + appId = identity.claims().get(AuthenticationConstants.AUTHORIZED_PARTY); + } else { + // Unknown Version. Not Authorized. + throw new AuthenticationException(String.format("Unknown Emulator Token version '%s'.", tokenVersion)); + } + + if (!credentials.isValidAppIdAsync(appId).join()) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appId)); + } + + return identity; + }); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java index 4182b11c0..1ed646059 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java @@ -1,18 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector.authentication; import java.util.List; public abstract class EndorsementsValidator { - /** * Verify that the set of ChannelIds, which come from the incoming activities, * all match the endorsements found on the JWT Token. * For example, if an Activity comes from webchat, that channelId says * says "webchat" and the jwt token endorsement MUST match that. - * @param channelId The channel name, typically extracted from the activity.ChannelId field, that - * to which the Activity is affinitized. + * + * @param channelId The channel name, typically extracted from the activity.ChannelId field, that + * to which the Activity is affinitized. * @param endorsements Whoever signed the JWT token is permitted to send activities only for - * some specific channels. That list is the endorsement list, and is validated here against the channelId. + * some specific channels. That list is the endorsement list, and is validated here against the channelId. * @return True is the channelId is found in the Endorsement set. False if the channelId is not found. */ public static boolean validate(String channelId, List endorsements) { @@ -35,12 +38,6 @@ public static boolean validate(String channelId, List endorsements) { // JwtTokenExtractor // Does the set of endorsements match the channelId that was passed in? - - // ToDo: Consider moving this to a HashSet instead of a string - // array, to make lookups O(1) instead of O(N). To give a sense - // of scope, tokens from WebChat have about 10 endorsements, and - // tokens coming from Teams have about 20. - return endorsements.contains(channelId); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java new file mode 100644 index 000000000..4c1264add --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +import com.microsoft.aad.adal4j.AuthenticationException; +import org.apache.commons.lang3.StringUtils; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class EnterpriseChannelValidation { + private static final TokenValidationParameters ENTERPRISE_VALIDATION_PARAMETERS = new TokenValidationParameters() {{ + this.validateIssuer = true; + this.validIssuers = new ArrayList() {{ + add(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); + }}; + this.validateAudience = false; + this.validateLifetime = true; + this.clockSkew = Duration.ofMinutes(5); + this.requireSignedTokens = true; + }}; + + /** + * Validate the incoming Auth Header as a token sent from a Bot Framework Channel Service. + * A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. + * @param channelId The ID of the channel to validate. + * @return A valid ClaimsIdentity. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + return authenticateToken(authHeader, credentials, channelProvider, serviceUrl, channelId, new AuthenticationConfiguration()); + } + + /** + * Validate the incoming Auth Header as a token sent from a Bot Framework Channel Service. + * A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. + * @param channelId The ID of the channel to validate. + * @param authConfig The authentication configuration. + * @return A valid ClaimsIdentity. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + if (authConfig == null) { + throw new AuthenticationException("Missing AuthenticationConfiguration"); + } + + return channelProvider.getChannelService() + + .thenCompose(channelService -> { + JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( + ENTERPRISE_VALIDATION_PARAMETERS, + String.format(AuthenticationConstants.TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT, channelService), + AuthenticationConstants.AllowedSigningAlgorithms); + + return tokenExtractor.getIdentityAsync(authHeader, channelId, authConfig.requiredEndorsements()); + }) + + .thenCompose(identity -> { + if (identity == null) { + // No valid identity. Not Authorized. + throw new AuthenticationException("Invalid Identity"); + } + + return validateIdentity(identity, credentials, serviceUrl); + }); + } + + public static CompletableFuture validateIdentity(ClaimsIdentity identity, CredentialProvider credentials, String serviceUrl) { + return CompletableFuture.supplyAsync(() -> { + if (identity == null || !identity.isAuthenticated()) { + throw new AuthenticationException("Invalid Identity"); + } + + // Now check that the AppID in the claim set matches + // what we're looking for. Note that in a multi-tenant bot, this value + // comes from developer code that may be reaching out to a service, hence the + // Async validation. + + // The AppId from the claim in the token must match the AppId specified by the developer. Note that + // the Bot Framework uses the Audience claim ("aud") to pass the AppID. + String appIdFromClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromClaim)) { + // Claim is present, but doesn't have a value. Not Authorized. + throw new AuthenticationException("Token Not Authenticated"); + } + + boolean isValid = credentials.isValidAppIdAsync(appIdFromClaim).join(); + if (!isValid) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); + } + + String serviceUrlClaim = identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); + if (StringUtils.isEmpty(serviceUrl)) { + throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); + } + + if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { + throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); + } + + return identity; + }); + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java new file mode 100644 index 000000000..9608f98be --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +/** + * Values and Constants used for Authentication and Authorization by the Bot Framework Protocol + * to US Government DataCenters. + */ +public class GovernmentAuthenticationConstants { + public static final String CHANNELSERVICE = "https://botframework.azure.us"; + + /** + * TO GOVERNMENT CHANNEL FROM BOT: Login URL. + */ + public static final String TO_CHANNEL_FROM_BOT_LOGIN_URL = "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e"; + + /** + * TO GOVERNMENT CHANNEL FROM BOT: OAuth scope to request. + */ + public static final String TO_CHANNEL_FROM_BOT_OAUTH_SCOPE = "https://api.botframework.us"; + + /** + * TO BOT FROM GOVERNMENT CHANNEL: Token issuer. + */ + public static final String TO_BOT_FROM_CHANNEL_TOKEN_ISSUER = "https://api.botframework.us"; + + /** + * OAuth Url used to get a token from OAuthApiClient. + */ + public static final String OAUTH_URL_GOV = "https://api.botframework.azure.us"; + + /** + * TO BOT FROM GOVERNMANT CHANNEL: OpenID metadata document for tokens coming from MSA. + */ + public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = "https://login.botframework.azure.us/v1/.well-known/openidconfiguration"; + + /** + * TO BOT FROM GOVERNMENT EMULATOR: OpenID metadata document for tokens coming from MSA. + */ + public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0/.well-known/openid-configuration"; +} + diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java new file mode 100644 index 000000000..e4e18e5c1 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +import com.microsoft.aad.adal4j.AuthenticationException; +import com.microsoft.bot.connector.ExecutorFactory; +import org.apache.commons.lang3.StringUtils; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; + +/** + * TO BOT FROM GOVERNMENT CHANNEL: Token validation parameters when connecting to a bot. + */ +public class GovernmentChannelValidation { + private static final TokenValidationParameters GOVERNMENT_VALIDATION_PARAMETERS = new TokenValidationParameters() {{ + this.validateIssuer = true; + this.validIssuers = new ArrayList() {{ + add(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); + }}; + this.validateAudience = false; + this.validateLifetime = true; + this.clockSkew = Duration.ofMinutes(5); + this.requireSignedTokens = true; + }}; + + /** + * Validate the incoming Auth Header as a token sent from a Bot Framework Government Channel Service. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param serviceUrl The service url from the request. + * @param channelId The ID of the channel to validate. + * @return A CompletableFuture representing the asynchronous operation. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId) { + return authenticateToken(authHeader, credentials, serviceUrl, channelId, new AuthenticationConfiguration()); + } + + /** + * Validate the incoming Auth Header as a token sent from a Bot Framework Government Channel Service. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param serviceUrl The service url from the request. + * @param channelId The ID of the channel to validate. + * @param authConfig The authentication configuration. + * @return A CompletableFuture representing the asynchronous operation. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) { + JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( + GOVERNMENT_VALIDATION_PARAMETERS, + GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, + AuthenticationConstants.AllowedSigningAlgorithms); + + return tokenExtractor.getIdentityAsync(authHeader, channelId, authConfig.requiredEndorsements()) + .thenCompose(identity -> { + return validateIdentity(identity, credentials, serviceUrl); + }); + } + + /** + * Validate the ClaimsIdentity as sent from a Bot Framework Government Channel Service. + * + * @param identity The claims identity to validate. + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param serviceUrl The service url from the request. + * @return A CompletableFuture representing the asynchronous operation. + */ + public static CompletableFuture validateIdentity(ClaimsIdentity identity, CredentialProvider credentials, String serviceUrl) { + + return CompletableFuture.supplyAsync(() -> { + if (identity == null || !identity.isAuthenticated()) { + throw new AuthenticationException("Invalid Identity"); + } + + return identity; + }, ExecutorFactory.getExecutor()) + + .thenApply(theIdentity -> { + // Now check that the AppID in the claim set matches + // what we're looking for. Note that in a multi-tenant bot, this value + // comes from developer code that may be reaching out to a service, hence the + // Async validation. + + // The AppId from the claim in the token must match the AppId specified by the developer. Note that + // the Bot Framework uses the Audience claim ("aud") to pass the AppID. + String appIdFromClaim = theIdentity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromClaim)) { + // Claim is present, but doesn't have a value. Not Authorized. + throw new AuthenticationException("Token Not Authenticated"); + } + + boolean isValid = credentials.isValidAppIdAsync(appIdFromClaim).join(); + if (!isValid) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); + } + + String serviceUrlClaim = theIdentity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); + if (StringUtils.isEmpty(serviceUrl)) { + throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); + } + + if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { + throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); + } + + return theIdentity; + }); + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java index 3273a846e..76bef99e7 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java @@ -10,18 +10,17 @@ import com.auth0.jwt.interfaces.Verification; import com.microsoft.aad.adal4j.AuthenticationException; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.logging.Level; -import java.util.logging.Logger; public class JwtTokenExtractor { - private static final Logger LOGGER = Logger.getLogger(OpenIdMetadata.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdMetadata.class); private static final ConcurrentMap openIdMetadataCache = new ConcurrentHashMap<>(); @@ -37,30 +36,34 @@ public JwtTokenExtractor(TokenValidationParameters tokenValidationParameters, St } public CompletableFuture getIdentityAsync(String authorizationHeader, String channelId) { + return getIdentityAsync(authorizationHeader, channelId, new ArrayList<>()); + } + + public CompletableFuture getIdentityAsync(String authorizationHeader, String channelId, List requiredEndorsements) { if (authorizationHeader == null) { return CompletableFuture.completedFuture(null); } String[] parts = authorizationHeader.split(" "); if (parts.length == 2) { - return getIdentityAsync(parts[0], parts[1], channelId); + return getIdentityAsync(parts[0], parts[1], channelId, requiredEndorsements); } return CompletableFuture.completedFuture(null); } - public CompletableFuture getIdentityAsync(String schema, String token, String channelId) { + public CompletableFuture getIdentityAsync(String schema, String token, String channelId, List requiredEndorsements) { // No header in correct scheme or no token if (!schema.equalsIgnoreCase("bearer") || token == null) { return CompletableFuture.completedFuture(null); } // Issuer isn't allowed? No need to check signature - if (!this.hasAllowedIssuer(token)) { + if (!hasAllowedIssuer(token)) { return CompletableFuture.completedFuture(null); } - return this.validateTokenAsync(token, channelId); + return validateTokenAsync(token, channelId, requiredEndorsements); } private boolean hasAllowedIssuer(String token) { @@ -69,11 +72,15 @@ private boolean hasAllowedIssuer(String token) { } @SuppressWarnings("unchecked") - private CompletableFuture validateTokenAsync(String token, String channelId) { + private CompletableFuture validateTokenAsync(String token, String channelId, List requiredEndorsements) { DecodedJWT decodedJWT = JWT.decode(token); OpenIdMetadataKey key = this.openIdMetadata.getKey(decodedJWT.getKeyId()); - if (key != null) { + if (key == null) { + return CompletableFuture.completedFuture(null); + } + + return CompletableFuture.supplyAsync(() -> { Verification verification = JWT.require(Algorithm.RSA256(key.key, null)); try { verification.build().verify(token); @@ -87,26 +94,25 @@ private CompletableFuture validateTokenAsync(String token, Strin if (!isEndorsed) { throw new AuthenticationException(String.format("Could not validate endorsement for key: %s with endorsements: %s", key.key.toString(), StringUtils.join(key.endorsements))); } + + // Verify that additional endorsements are satisfied. If no additional endorsements are expected, the requirement is satisfied as well + boolean additionalEndorsementsSatisfied = + requiredEndorsements.stream().allMatch((endorsement) -> EndorsementsValidator.validate(endorsement, key.endorsements)); + if (!additionalEndorsementsSatisfied) { + throw new AuthenticationException(String.format("Could not validate additional endorsement for key: %s with endorsements: %s", key.key.toString(), StringUtils.join(requiredEndorsements))); + } } if (!this.allowedSigningAlgorithms.contains(decodedJWT.getAlgorithm())) { throw new AuthenticationException(String.format("Could not validate algorithm for key: %s with algorithms: %s", decodedJWT.getAlgorithm(), StringUtils.join(allowedSigningAlgorithms))); } - Map claims = new HashMap<>(); - if (decodedJWT.getClaims() != null) { - decodedJWT.getClaims().forEach((k, v) -> claims.put(k, v.asString())); - } - - return CompletableFuture.completedFuture(new ClaimsIdentityImpl(decodedJWT.getIssuer(), claims)); - + return new ClaimsIdentity(decodedJWT); } catch (JWTVerificationException ex) { String errorDescription = ex.getMessage(); - LOGGER.log(Level.WARNING, errorDescription); - return CompletableFuture.completedFuture(null); + LOGGER.warn(errorDescription); + throw new AuthenticationException(ex); } - } - - return CompletableFuture.completedFuture(null); + }); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 0c5ebd3dd..0398d97b5 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -5,6 +5,7 @@ import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.bot.schema.models.Activity; +import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -17,48 +18,100 @@ public class JwtTokenValidation { * @param activity The incoming Activity from the Bot Framework or the Emulator * @param authHeader The Bearer token included as part of the request * @param credentials The set of valid credentials, such as the Bot Application ID - * @return Nothing + * @return A task that represents the work queued to execute. * @throws AuthenticationException Throws on auth failed. */ - public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials) throws AuthenticationException, InterruptedException, ExecutionException { - if (authHeader == null || authHeader.isEmpty()) { + public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials, ChannelProvider channelProvider) throws AuthenticationException, InterruptedException, ExecutionException { + return authenticateRequest(activity, authHeader, credentials, channelProvider, new AuthenticationConfiguration()); + } + + /** + * Validates the security tokens required by the Bot Framework Protocol. Throws on any exceptions. + * + * @param activity The incoming Activity from the Bot Framework or the Emulator + * @param authHeader The Bearer token included as part of the request + * @param credentials The set of valid credentials, such as the Bot Application ID + * @param authConfig The authentication configuration. + * @return A task that represents the work queued to execute. + * @throws AuthenticationException Throws on auth failed. + */ + public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, AuthenticationConfiguration authConfig) throws AuthenticationException, InterruptedException, ExecutionException { + if (StringUtils.isEmpty(authHeader)) { // No auth header was sent. We might be on the anonymous code path. boolean isAuthDisable = credentials.isAuthenticationDisabledAsync().get(); if (isAuthDisable) { // In the scenario where Auth is disabled, we still want to have the // IsAuthenticated flag set in the ClaimsIdentity. To do this requires // adding in an empty claim. - return CompletableFuture.completedFuture(new ClaimsIdentityImpl("anonymous")); + return CompletableFuture.completedFuture(new ClaimsIdentity("anonymous")); } // No Auth Header. Auth is required. Request is not authorized. - throw new AuthenticationException("No Auth Header. Auth is required."); + CompletableFuture result = CompletableFuture.completedFuture(null); + result.completeExceptionally(new AuthenticationException("No Auth Header. Auth is required.")); + return result; } // Go through the standard authentication path. - ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(authHeader, credentials, activity.channelId(), activity.serviceUrl()).get(); + return JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.channelId(), activity.serviceUrl(), authConfig) + .thenApply(identity -> { + // On the standard Auth path, we need to trust the URL that was incoming. + MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); - // On the standard Auth path, we need to trust the URL that was incoming. - MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); - return CompletableFuture.completedFuture(identity); + return identity; + }); } - // TODO: Recieve httpClient and use ClientID - public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { - if (authHeader == null || authHeader.isEmpty()) { + /** + * Validates the authentication header of an incoming request. + * + * @param authHeader The authentication header to validate. + * @param credentials The bot's credential provider. + * @param channelProvider The bot's channel service provider. + * @param channelId The ID of the channel that sent the request. + * @param serviceUrl The service URL for the activity. + * @return A task that represents the work queued to execute. + * @throws ExecutionException + * @throws InterruptedException + * @throws AuthenticationException + */ + public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { + return validateAuthHeader(authHeader, credentials, channelProvider, channelId, serviceUrl, new AuthenticationConfiguration()); + } + + /** + * Validates the authentication header of an incoming request. + * + * @param authHeader The authentication header to validate. + * @param credentials The bot's credential provider. + * @param channelProvider The bot's channel service provider. + * @param channelId The ID of the channel that sent the request. + * @param serviceUrl The service URL for the activity. + * @param authConfig The authentication configuration. + * @return A task that represents the work queued to execute. + * @throws ExecutionException + * @throws InterruptedException + * @throws AuthenticationException + */ + public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + if (StringUtils.isEmpty(authHeader)) { throw new IllegalArgumentException("No authHeader present. Auth is required."); } - boolean usingEmulator = EmulatorValidation.isTokenFromEmulator(authHeader).get(); + boolean usingEmulator = EmulatorValidation.isTokenFromEmulator(authHeader); if (usingEmulator) { - return EmulatorValidation.authenticateToken(authHeader, credentials, channelId); - } else { + return EmulatorValidation.authenticateToken(authHeader, credentials, channelProvider, channelId, authConfig); + } else if (channelProvider == null || channelProvider.isPublicAzure()) { // No empty or null check. Empty can point to issues. Null checks only. if (serviceUrl != null) { - return ChannelValidation.authenticateToken(authHeader, credentials, channelId, serviceUrl); + return ChannelValidation.authenticateToken(authHeader, credentials, channelId, serviceUrl, authConfig); } else { - return ChannelValidation.authenticateToken(authHeader, credentials, channelId); + return ChannelValidation.authenticateToken(authHeader, credentials, channelId, authConfig); } + } else if (channelProvider.isGovernment()) { + return GovernmentChannelValidation.authenticateToken(authHeader, credentials, serviceUrl, channelId, authConfig); + } else { + return EnterpriseChannelValidation.authenticateToken(authHeader, credentials, channelProvider, serviceUrl, channelId, authConfig); } } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index 9f991651c..d958a89a1 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -3,11 +3,12 @@ package com.microsoft.bot.connector.authentication; -import com.fasterxml.jackson.annotation.JsonProperty; import com.microsoft.aad.adal4j.AuthenticationResult; import com.microsoft.aad.adal4j.ClientCredential; import com.microsoft.rest.credentials.ServiceClientCredentials; -import okhttp3.*; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; import org.slf4j.LoggerFactory; import java.net.MalformedURLException; @@ -22,8 +23,20 @@ * MicrosoftAppCredentials auth implementation */ public class MicrosoftAppCredentials implements ServiceClientCredentials { + public static final String MICROSOFTAPPID = "MicrosoftAppId"; + public static final String MICROSOFTAPPPASSWORD = "MicrosoftAppPassword"; + + public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static final MediaType FORM_ENCODE = MediaType.parse("application/x-www-form-urlencoded"); + private static ConcurrentMap trustHostNames = new ConcurrentHashMap<>(); + + static { + trustHostNames.put("api.botframework.com", LocalDateTime.MAX); + trustHostNames.put("token.botframework.com", LocalDateTime.MAX); + trustHostNames.put("api.botframework.azure.us", LocalDateTime.MAX); + trustHostNames.put("token.botframework.azure.us", LocalDateTime.MAX); + } private String appId; private String appPassword; @@ -45,27 +58,69 @@ public static MicrosoftAppCredentials empty() { return new MicrosoftAppCredentials(null, null); } + public static void trustServiceUrl(URI serviceUrl) { + trustServiceUrl(serviceUrl.toString(), LocalDateTime.now().plusDays(1)); + } + + public static void trustServiceUrl(String serviceUrl) { + trustServiceUrl(serviceUrl, LocalDateTime.now().plusDays(1)); + } + + public static void trustServiceUrl(String serviceUrl, LocalDateTime expirationTime) { + try { + URL url = new URL(serviceUrl); + trustServiceUrl(url, expirationTime); + } catch (MalformedURLException e) { + LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); + } + } + + public static void trustServiceUrl(URL serviceUrl, LocalDateTime expirationTime) { + trustHostNames.put(serviceUrl.getHost(), expirationTime); + } + + public static boolean isTrustedServiceUrl(String serviceUrl) { + try { + URL url = new URL(serviceUrl); + return isTrustedServiceUrl(url); + } catch (MalformedURLException e) { + LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); + return false; + } + } + + public static boolean isTrustedServiceUrl(URL url) { + return !trustHostNames.getOrDefault(url.getHost(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); + } + + public static boolean isTrustedServiceUrl(HttpUrl url) { + return !trustHostNames.getOrDefault(url.host(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); + } + public String appId() { return this.appId; } - public String appPassword(){ return this.appPassword; } + + public String appPassword() { + return this.appPassword; + } public MicrosoftAppCredentials withAppId(String appId) { this.appId = appId; return this; } - public MicrosoftAppCredentials withAppPassword(String appPassword){ + public MicrosoftAppCredentials withAppPassword(String appPassword) { this.appPassword = appPassword; return this; } - public String channelAuthTenant(){ - return channelAuthTenant == null?AuthenticationConstants.DefaultChannelAuthTenant:channelAuthTenant; + public String channelAuthTenant() { + return channelAuthTenant == null ? AuthenticationConstants.DEFAULT_CHANNEL_AUTH_TENANT : channelAuthTenant; } public void setChannelAuthTenant(String authTenant) throws MalformedURLException { - channelAuthTenant = (new URL(authTenant)).toString(); + channelAuthTenant = new URL(authTenant).toString(); } public MicrosoftAppCredentials withChannelAuthTenant(String authTenant) throws MalformedURLException { @@ -73,12 +128,12 @@ public MicrosoftAppCredentials withChannelAuthTenant(String authTenant) throws M return this; } - public String oAuthEndpoint(){ - return String.format(AuthenticationConstants.ToChannelFromBotLoginUrlTemplate, channelAuthTenant()); + public String oAuthEndpoint() { + return String.format(AuthenticationConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL_TEMPLATE, channelAuthTenant()); } - public String oAuthScope(){ - return AuthenticationConstants.ToChannelFromBotOAuthScope; + public String oAuthScope() { + return AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE; } public Future getToken() throws MalformedURLException { @@ -86,11 +141,11 @@ public Future getToken() throws MalformedURLException { } protected boolean ShouldSetToken(String url) { - return isTrustedServiceUrl(url); + return isTrustedServiceUrl(url); } private AdalAuthenticator getAuthenticator() throws MalformedURLException { - if(this.authenticator == null) { + if (this.authenticator == null) { this.authenticator = new AdalAuthenticator( new ClientCredential(this.appId, this.appPassword), new OAuthConfiguration(oAuthEndpoint(), oAuthScope())); @@ -102,52 +157,4 @@ private AdalAuthenticator getAuthenticator() throws MalformedURLException { public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) { clientBuilder.interceptors().add(new MicrosoftAppCredentialsInterceptor(this)); } - - public static void trustServiceUrl(URI serviceUrl) { - trustServiceUrl(serviceUrl.toString(), LocalDateTime.now().plusDays(1)); - } - - public static void trustServiceUrl(String serviceUrl) { - trustServiceUrl(serviceUrl, LocalDateTime.now().plusDays(1)); - } - - public static void trustServiceUrl(String serviceUrl, LocalDateTime expirationTime) { - try { - URL url = new URL(serviceUrl); - trustServiceUrl(url, expirationTime); - } catch (MalformedURLException e) { - LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); - } - } - - public static void trustServiceUrl(URL serviceUrl, LocalDateTime expirationTime) { - trustHostNames.put(serviceUrl.getHost(), expirationTime); - } - - public static boolean isTrustedServiceUrl(String serviceUrl) { - try { - URL url = new URL(serviceUrl); - return isTrustedServiceUrl(url); - } catch (MalformedURLException e) { - LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("trustServiceUrl", e); - return false; - } - } - - public static boolean isTrustedServiceUrl(URL url) { - return !trustHostNames.getOrDefault(url.getHost(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); - } - - public static boolean isTrustedServiceUrl(HttpUrl url) { - return !trustHostNames.getOrDefault(url.host(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); - } - - private static ConcurrentMap trustHostNames = new ConcurrentHashMap<>(); - - static { - trustHostNames.put("api.botframework.com", LocalDateTime.MAX); - trustHostNames.put("token.botframework.com", LocalDateTime.MAX); - trustHostNames.put("api.botframework.azure.us", LocalDateTime.MAX); - trustHostNames.put("token.botframework.azure.us", LocalDateTime.MAX); - } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java index 2e52de065..1ee3765bc 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentialsInterceptor.java @@ -34,7 +34,7 @@ public Response intercept(Chain chain) throws IOException { String token; try { token = this.credentials.getToken().get().getAccessToken(); - } catch(Throwable t){ + } catch (Throwable t) { throw new IOException(t); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftGovernmentAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftGovernmentAppCredentials.java new file mode 100644 index 000000000..70e737dd4 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftGovernmentAppCredentials.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +/** + * MicrosoftGovernmentAppCredentials auth implementation. + */ +public class MicrosoftGovernmentAppCredentials extends MicrosoftAppCredentials { + /** + * Initializes a new instance of the MicrosoftGovernmentAppCredentials class. + * + * @param appId The Microsoft app ID. + * @param password The Microsoft app password. + */ + public MicrosoftGovernmentAppCredentials(String appId, String password) { + super(appId, password); + } + + public static MicrosoftGovernmentAppCredentials empty() { + return new MicrosoftGovernmentAppCredentials(null, null); + } + + /** + * Gets the OAuth endpoint to use. + * + * @return The OAuth endpoint to use. + */ + @Override + public String oAuthEndpoint() { + return GovernmentAuthenticationConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL; + } + + /** + * Gets the OAuth scope to use. + * + * @return The OAuth scope to use. + */ + @Override + public String oAuthScope() { + return GovernmentAuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE; + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java index 0b10f9d49..d37d2ac72 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java @@ -1,9 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector.authentication; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.microsoft.bot.connector.UserAgent; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.TokenExchangeState; import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ConversationReference; @@ -41,13 +44,13 @@ * Uses the MicrosoftInterceptor class to add Authorization header from idp. */ public class OAuthClient extends ServiceClient { - private final ConnectorClientImpl client; + private final RestConnectorClient client; private final String uri; private ObjectMapper mapper; - public OAuthClient(ConnectorClientImpl client, String uri) throws URISyntaxException, MalformedURLException { + public OAuthClient(RestConnectorClient client, String uri) throws URISyntaxException, MalformedURLException { super(client.restClient()); URI uriResult = new URI(uri); @@ -69,7 +72,7 @@ public OAuthClient(ConnectorClientImpl client, String uri) throws URISyntaxExcep * @param userId * @param connectionName * @param magicCode - * @return CompletableFuture< TokenResponse > on success; otherwise null. + * @return CompletableFuture on success; otherwise null. */ public CompletableFuture GetUserTokenAsync(String userId, String connectionName, String magicCode) throws IOException, URISyntaxException, ExecutionException, InterruptedException { return GetUserTokenAsync(userId, connectionName, magicCode, null); @@ -77,14 +80,14 @@ public CompletableFuture GetUserTokenAsync(String userId, String protected URI MakeUri(String uri, HashMap queryStrings) throws URISyntaxException { String newUri = queryStrings.keySet().stream() - .map(key -> { - try { - return key + "=" + URLEncoder.encode(queryStrings.get(key), StandardCharsets.UTF_8.toString()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - }) - .collect(joining("&", uri.endsWith("?") ? uri : uri + "?", "")); + .map(key -> { + try { + return key + "=" + URLEncoder.encode(queryStrings.get(key), StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + }) + .collect(joining("&", uri.endsWith("?") ? uri : uri + "?", "")); return new URI(newUri); @@ -97,7 +100,7 @@ protected URI MakeUri(String uri, HashMap queryStrings) throws U * @param connectionName * @param magicCode * @param customHeaders - * @return CompletableFuture< TokenResponse > on success; null otherwise. + * @return CompletableFuture on success; null otherwise. */ public CompletableFuture GetUserTokenAsync(String userId, String connectionName, String magicCode, Map> customHeaders) throws IllegalArgumentException { if (StringUtils.isEmpty(userId)) { @@ -132,13 +135,13 @@ public CompletableFuture GetUserTokenAsync(String userId, String // Later: Use client in clientimpl? OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) - .build(); + .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) + .build(); Request request = new Request.Builder() - .url(tokenUrl.toString()) - .header("User-Agent", UserAgent.value()) - .build(); + .url(tokenUrl.toString()) + .header("User-Agent", UserAgent.value()) + .build(); Response response = null; try { @@ -198,14 +201,14 @@ public CompletableFuture SignOutUserAsync(String userId, String connect // Later: Use client in clientimpl? OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) - .build(); + .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) + .build(); Request request = new Request.Builder() - .delete() - .url(tokenUrl.toString()) - .header("User-Agent", UserAgent.value()) - .build(); + .delete() + .url(tokenUrl.toString()) + .header("User-Agent", UserAgent.value()) + .build(); Response response = null; try { @@ -238,15 +241,15 @@ public CompletableFuture GetSignInLinkAsync(Activity activity, String co } final MicrosoftAppCredentials creds = (MicrosoftAppCredentials) this.client.restClient().credentials(); TokenExchangeState tokenExchangeState = new TokenExchangeState() - .withConnectionName(connectionName) - .withConversation(new ConversationReference() - .withActivityId(activity.id()) - .withBot(activity.recipient()) - .withChannelId(activity.channelId()) - .withConversation(activity.conversation()) - .withServiceUrl(activity.serviceUrl()) - .withUser(activity.from())) - .withMsAppId((creds == null) ? null : creds.appId()); + .withConnectionName(connectionName) + .withConversation(new ConversationReference() + .withActivityId(activity.id()) + .withBot(activity.recipient()) + .withChannelId(activity.channelId()) + .withConversation(activity.conversation()) + .withServiceUrl(activity.serviceUrl()) + .withUser(activity.from())) + .withMsAppId((creds == null) ? null : creds.appId()); String serializedState = this.mapper.writeValueAsString(tokenExchangeState); @@ -266,13 +269,13 @@ public CompletableFuture GetSignInLinkAsync(Activity activity, String co // Later: Use client in clientimpl? OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(new MicrosoftAppCredentialsInterceptor(creds)) - .build(); + .addInterceptor(new MicrosoftAppCredentialsInterceptor(creds)) + .build(); Request request = new Request.Builder() - .url(tokenUrl.toString()) - .header("User-Agent", UserAgent.value()) - .build(); + .url(tokenUrl.toString()) + .header("User-Agent", UserAgent.value()) + .build(); Response response = null; try { @@ -313,14 +316,14 @@ public CompletableFuture SendEmulateOAuthCardsAsync(Boolean emulateOAuthCards) t // Later: Use client in clientimpl? OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) - .build(); + .addInterceptor(new MicrosoftAppCredentialsInterceptor(appCredentials)) + .build(); Request request = new Request.Builder() - .url(tokenUrl.toString()) - .header("User-Agent", UserAgent.value()) - .post(body) - .build(); + .url(tokenUrl.toString()) + .header("User-Agent", UserAgent.value()) + .post(body) + .build(); Response response = null; try { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java index bff9076a1..133182caa 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthConfiguration.java @@ -11,44 +11,48 @@ public class OAuthConfiguration { private String scope; private String authority; - public OAuthConfiguration(String authority, String scope){ + public OAuthConfiguration(String authority, String scope) { this.authority = authority; this.scope = scope; } /** * Sets oAuth Authority for authentication. + * * @param authority * @return This OAuthConfiguration object. */ - public OAuthConfiguration withAuthority(String authority){ + public OAuthConfiguration withAuthority(String authority) { this.authority = authority; return this; } /** * Gets oAuth Authority for authentication. + * * @return OAuth Authority for authentication. */ - public String authority(){ + public String authority() { return authority; } /** * Sets oAuth scope for authentication. + * * @param scope * @return This OAuthConfiguration object. */ - public OAuthConfiguration withScope(String scope){ + public OAuthConfiguration withScope(String scope) { this.scope = scope; return this; } /** * Gets oAuth scope for authentication. + * * @return OAuth scope for authentication. */ - public String scope(){ + public String scope() { return scope; } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java index 45378175f..69624c073 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java @@ -20,17 +20,17 @@ import java.util.logging.Logger; class OpenIdMetadata { - private static final Logger LOGGER = Logger.getLogger( OpenIdMetadata.class.getName() ); + private static final Logger LOGGER = Logger.getLogger( OpenIdMetadata.class.getName() ); - private String url; - private long lastUpdated; - private JwkProvider cacheKeys; - private ObjectMapper mapper; + private String url; + private long lastUpdated; + private JwkProvider cacheKeys; + private ObjectMapper mapper; - OpenIdMetadata(String url) { - this.url = url; - this.mapper = new ObjectMapper().findAndRegisterModules(); - } + OpenIdMetadata(String url) { + this.url = url; + this.mapper = new ObjectMapper().findAndRegisterModules(); + } public OpenIdMetadataKey getKey(String keyId) { // If keys are more than 5 days old, refresh them diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ResponseFuture.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ResponseFuture.java deleted file mode 100644 index 61baa17c8..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ResponseFuture.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.microsoft.bot.connector.authentication; - -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.Response; - -public class ResponseFuture implements Callback { - public final CompletableFuture future = new CompletableFuture(); - public Call call; - - public ResponseFuture(Call call) { - this.call = call; - } - - @Override public void onFailure(Call call, IOException e) { - future.completeExceptionally(e); - } - - @Override public void onResponse(Call call, Response response) throws IOException { - future.complete(response); - } -} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleChannelProvider.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleChannelProvider.java new file mode 100644 index 000000000..9bc4fad0a --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleChannelProvider.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector.authentication; + +import org.apache.commons.lang3.StringUtils; + +import java.util.concurrent.CompletableFuture; + +public class SimpleChannelProvider implements ChannelProvider { + private String channelService; + + /** + * Creates a SimpleChannelProvider with no ChannelService which will use Public Azure. + */ + public SimpleChannelProvider() { + + } + + /** + * Creates a SimpleChannelProvider with the specified ChannelService. + * + * @param channelService The ChannelService to use. Null or empty strings represent Public Azure, + * the string 'https://botframework.us' represents US Government Azure, and + * other values are for private channels. + */ + public SimpleChannelProvider(String channelService) { + this.channelService = channelService; + } + + @Override + public CompletableFuture getChannelService() { + return CompletableFuture.completedFuture(channelService); + } + + @Override + public boolean isGovernment() { + return GovernmentAuthenticationConstants.CHANNELSERVICE.equalsIgnoreCase(channelService); + } + + @Override + public boolean isPublicAzure() { + return StringUtils.isEmpty(channelService); + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java index cc3e0a119..ce5789611 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java @@ -1,15 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector.authentication; import org.apache.commons.lang3.StringUtils; + import java.util.concurrent.CompletableFuture; +/** + * A simple implementation of the CredentialProvider interface. + */ public class SimpleCredentialProvider implements CredentialProvider { private String appId; private String password; - + /** + * Initializes a new instance with empty credentials. + */ public SimpleCredentialProvider() { } + + /** + * Initializes a new instance with the provided credentials. + * + * @param appId The app ID. + * @param password The app password. + */ public SimpleCredentialProvider(String appId, String password) { this.appId = appId; this.password = password; @@ -18,6 +34,7 @@ public SimpleCredentialProvider(String appId, String password) { public String getAppId() { return this.appId; } + public void setAppId(String appId) { this.appId = appId; } @@ -25,24 +42,23 @@ public void setAppId(String appId) { public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } @Override public CompletableFuture isValidAppIdAsync(String appId) { - return CompletableFuture.completedFuture(appId == this.appId); + return CompletableFuture.completedFuture(StringUtils.equals(appId, this.appId)); } @Override public CompletableFuture getAppPasswordAsync(String appId) { - return CompletableFuture.completedFuture((appId == this.appId) ? this.password : null); + return CompletableFuture.completedFuture(StringUtils.equals(appId, this.appId) ? this.password : null); } @Override public CompletableFuture isAuthenticationDisabledAsync() { return CompletableFuture.completedFuture(StringUtils.isEmpty(this.appId)); } - - } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java index b27706033..75affa36d 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java @@ -7,8 +7,6 @@ import java.util.ArrayList; import java.util.List; -import static com.microsoft.bot.connector.authentication.AuthenticationConstants.ToBotFromChannelTokenIssuer; - public class TokenValidationParameters { public boolean validateIssuer; public List validIssuers; @@ -37,10 +35,12 @@ static TokenValidationParameters toBotFromEmulatorTokenValidationParameters() { return new TokenValidationParameters() {{ this.validateIssuer = true; this.validIssuers = new ArrayList() {{ - add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); - add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); - add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); - add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); + add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); // Auth v3.1, 1.0 token + add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); // Auth v3.1, 2.0 token + add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); // Auth v3.2, 1.0 token + add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); // Auth v3.2, 2.0 token + add("https://sts.windows.net/cab8a31a-1906-4287-a0d8-4eef66b95f6e/"); // Auth for US Gov, 1.0 token + add("https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0"); // Auth for US Gov, 2.0 token }}; this.validateAudience = false; this.validateLifetime = true; @@ -53,7 +53,7 @@ static TokenValidationParameters toBotFromChannelTokenValidationParameters() { return new TokenValidationParameters() {{ this.validateIssuer = true; this.validIssuers = new ArrayList() {{ - add(ToBotFromChannelTokenIssuer); + add(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); }}; this.validateAudience = false; this.validateLifetime = true; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/package-info.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/package-info.java new file mode 100644 index 000000000..b02693e21 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/package-info.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +/** + * This package contains the implementation auth classes for ConnectorClient. + */ +package com.microsoft.bot.connector.authentication; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/futureFromObservable.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/futureFromObservable.java deleted file mode 100644 index 4b326a809..000000000 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/futureFromObservable.java +++ /dev/null @@ -1,2 +0,0 @@ -package com.microsoft.bot.connector.implementation; - diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/package-info.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/package-info.java index 7517691b8..c4b63b1fc 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/package-info.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/package-info.java @@ -1,25 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for // license information. -// -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is -// regenerated. /** - * This package contains the classes for ConnectorClient. - * The Bot Connector REST API allows your bot to send and receive messages to channels configured in the - [Bot Framework Developer Portal](https://dev.botframework.com). The Connector service uses industry-standard REST - and JSON over HTTPS. - Client libraries for this REST API are available. See below for a list. - Many bots will use both the Bot Connector REST API and the associated [Bot State REST API](/en-us/restapi/state). The - Bot State REST API allows a bot to store and retrieve state associated with users and conversations. - Authentication for both the Bot Connector and Bot State REST APIs is accomplished with JWT Bearer tokens, and is - described in detail in the [Connector Authentication](/en-us/restapi/authentication) document. - # Client Libraries for the Bot Connector REST API - * [Bot Builder for C#](/en-us/csharp/builder/sdkreference/) - * [Bot Builder for Node.js](/en-us/node/builder/overview/) - * Generate your own from the [Connector API Swagger file](https://raw.githubusercontent.com/Microsoft/BotBuilder/master/CSharp/Library/Microsoft.Bot.Connector.Shared/Swagger/ConnectorAPI.json) - © 2016 Microsoft. + * This package contains the classes for Bot-Connector. */ package com.microsoft.bot.connector; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/models/ErrorResponseException.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java similarity index 87% rename from libraries/bot-connector/src/main/java/com/microsoft/bot/connector/models/ErrorResponseException.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java index 7e4a0f19f..390c35f13 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/models/ErrorResponseException.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java @@ -2,13 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. */ -package com.microsoft.bot.connector.models; +package com.microsoft.bot.connector.rest; import com.microsoft.rest.RestException;import com.microsoft.bot.schema.models.ErrorResponse; import okhttp3.ResponseBody; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/AttachmentsImpl.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java similarity index 95% rename from libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/AttachmentsImpl.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java index ccef8de03..68ba3f111 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/AttachmentsImpl.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java @@ -2,19 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. */ -package com.microsoft.bot.connector.implementation; +package com.microsoft.bot.connector.rest; import retrofit2.Retrofit; import com.microsoft.bot.connector.Attachments; import com.google.common.reflect.TypeToken; import com.microsoft.bot.schema.models.AttachmentInfo; -import com.microsoft.bot.connector.models.ErrorResponseException; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; @@ -34,11 +29,11 @@ * An instance of this class provides access to all the operations defined * in Attachments. */ -public class AttachmentsImpl implements Attachments { +public class RestAttachments implements Attachments { /** The Retrofit service to perform REST calls. */ private AttachmentsService service; /** The service client containing this operation class. */ - private ConnectorClientImpl client; + private RestConnectorClient client; /** * Initializes an instance of AttachmentsImpl. @@ -46,7 +41,7 @@ public class AttachmentsImpl implements Attachments { * @param retrofit the Retrofit instance built from a Retrofit Builder. * @param client the instance of the service client containing this operation class. */ - public AttachmentsImpl(Retrofit retrofit, ConnectorClientImpl client) { + RestAttachments(Retrofit retrofit, RestConnectorClient client) { this.service = retrofit.create(AttachmentsService.class); this.client = client; } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConnectorClientImpl.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java similarity index 81% rename from libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConnectorClientImpl.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java index e46eca1d3..ca92b46e4 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConnectorClientImpl.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java @@ -2,10 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * */ -package com.microsoft.bot.connector.implementation; +package com.microsoft.bot.connector.rest; import com.microsoft.azure.AzureClient; import com.microsoft.azure.AzureResponseBuilder; @@ -24,13 +23,28 @@ import java.util.Properties; /** - * Initializes a new instance of the ConnectorClientImpl class. + * The Bot Connector REST API allows your bot to send and receive messages + * to channels configured in the + * [Bot Framework Developer Portal](https://dev.botframework.com). The + * Connector service uses industry-standard REST + * and JSON over HTTPS. + * + * Client libraries for this REST API are available. See below for a list. + * + * Many bots will use both the Bot Connector REST API and the associated + * [Bot State REST API](/en-us/restapi/state). The + * Bot State REST API allows a bot to store and retrieve state associated + * with users and conversations. + * + * Authentication for both the Bot Connector and Bot State REST APIs is + * accomplished with JWT Bearer tokens, and is + * described in detail in the [Connector + * Authentication](/en-us/restapi/authentication) document. */ -public class ConnectorClientImpl extends AzureServiceClient implements ConnectorClient { +public class RestConnectorClient extends AzureServiceClient implements ConnectorClient { /** the {@link AzureClient} used for long running operations. */ private AzureClient azureClient; - /** * Gets the {@link AzureClient} used for long running operations. * @return the azure client; @@ -58,7 +72,7 @@ public String acceptLanguage() { * @param acceptLanguage the acceptLanguage value. * @return the service client itself */ - public ConnectorClientImpl withAcceptLanguage(String acceptLanguage) { + public RestConnectorClient withAcceptLanguage(String acceptLanguage) { this.acceptLanguage = acceptLanguage; return this; } @@ -68,7 +82,7 @@ public ConnectorClientImpl withAcceptLanguage(String acceptLanguage) { * TODO: Use this. */ private RetryStrategy retryStrategy = null; - public ConnectorClientImpl withRestRetryStrategy(RetryStrategy retryStrategy) { + public RestConnectorClient withRestRetryStrategy(RetryStrategy retryStrategy) { this.retryStrategy = retryStrategy; return this; } @@ -94,7 +108,7 @@ public int longRunningOperationRetryTimeout() { * @param longRunningOperationRetryTimeout the longRunningOperationRetryTimeout value. * @return the service client itself */ - public ConnectorClientImpl withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) { + public RestConnectorClient withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) { this.longRunningOperationRetryTimeout = longRunningOperationRetryTimeout; return this; } @@ -117,7 +131,7 @@ public boolean generateClientRequestId() { * @param generateClientRequestId the generateClientRequestId value. * @return the service client itself */ - public ConnectorClientImpl withGenerateClientRequestId(boolean generateClientRequestId) { + public RestConnectorClient withGenerateClientRequestId(boolean generateClientRequestId) { this.generateClientRequestId = generateClientRequestId; return this; } @@ -138,14 +152,14 @@ public Attachments attachments() { /** * The Conversations object to access its operations. */ - private ConversationsImpl conversations; + private RestConversations conversations; /** * Gets the Conversations object to access its operations. * @return the Conversations object. */ @Override - public ConversationsImpl conversations() { + public RestConversations conversations() { return this.conversations; } @@ -154,7 +168,7 @@ public ConversationsImpl conversations() { * * @param credentials the management credentials for Azure */ - public ConnectorClientImpl(ServiceClientCredentials credentials) { + public RestConnectorClient(ServiceClientCredentials credentials) { this("https://api.botframework.com", credentials); } @@ -164,7 +178,7 @@ public ConnectorClientImpl(ServiceClientCredentials credentials) { * @param baseUrl the base URL of the host * @param credentials the management credentials for Azure */ - public ConnectorClientImpl(String baseUrl, ServiceClientCredentials credentials) { + public RestConnectorClient(String baseUrl, ServiceClientCredentials credentials) { super(baseUrl, credentials); initialize(); } @@ -174,7 +188,7 @@ public ConnectorClientImpl(String baseUrl, ServiceClientCredentials credentials) * * @param restClient the REST client to connect to Azure. */ - public ConnectorClientImpl(RestClient restClient){ + public RestConnectorClient(RestClient restClient){ super(restClient); initialize(); } @@ -183,8 +197,8 @@ protected void initialize() { this.acceptLanguage = "en-US"; this.longRunningOperationRetryTimeout = 30; this.generateClientRequestId = true; - this.attachments = new AttachmentsImpl(restClient().retrofit(), this); - this.conversations = new ConversationsImpl(restClient().retrofit(), this); + this.attachments = new RestAttachments(restClient().retrofit(), this); + this.conversations = new RestConversations(restClient().retrofit(), this); this.azureClient = new AzureClient(this); @@ -192,7 +206,7 @@ protected void initialize() { String build_version; final Properties properties = new Properties(); try { - InputStream propStream = ConnectorClientImpl.class.getClassLoader().getResourceAsStream("project.properties"); + InputStream propStream = RestConnectorClient.class.getClassLoader().getResourceAsStream("project.properties"); properties.load(propStream); build_version = properties.getProperty("version"); } catch (IOException e) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConversationsImpl.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java similarity index 99% rename from libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConversationsImpl.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java index dfb2309f9..40d2d1d96 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/ConversationsImpl.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java @@ -2,12 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. - * - * NOT GENERATED. - * This uses Java 8 CompletionStage for async processing instead of JavaRX/Guava */ -package com.microsoft.bot.connector.implementation; +package com.microsoft.bot.connector.rest; import retrofit2.Retrofit; import com.microsoft.bot.connector.Conversations; @@ -19,7 +16,6 @@ import com.microsoft.bot.schema.models.ConversationResourceResponse; import com.microsoft.bot.schema.models.ConversationsResult; import com.microsoft.bot.schema.models.PagedMembersResult; -import com.microsoft.bot.connector.models.ErrorResponseException; import com.microsoft.bot.schema.models.ResourceResponse; import com.microsoft.bot.schema.models.Transcript; import com.microsoft.rest.ServiceCallback; @@ -49,11 +45,11 @@ * An instance of this class provides access to all the operations defined * in Conversations. */ -public class ConversationsImpl implements Conversations { +public class RestConversations implements Conversations { /** The Retrofit service to perform REST calls. */ private ConversationsService service; /** The service client containing this operation class. */ - private ConnectorClientImpl client; + private RestConnectorClient client; /** * Initializes an instance of ConversationsImpl. @@ -61,7 +57,7 @@ public class ConversationsImpl implements Conversations { * @param retrofit the Retrofit instance built from a Retrofit Builder. * @param client the instance of the service client containing this operation class. */ - public ConversationsImpl(Retrofit retrofit, ConnectorClientImpl client) { + RestConversations(Retrofit retrofit, RestConnectorClient client) { this.service = retrofit.create(ConversationsService.class); this.client = client; } @@ -284,8 +280,8 @@ public ConversationResourceResponse call(ServiceResponse> CreateConversationAsync(ConversationParameters parameters) { CompletableFuture> future_result = completableFutureFromObservable(createConversationAsync(parameters)); @@ -719,7 +715,7 @@ public Void call(ServiceResponse response) { } }); } - + /** * DeleteConversationMemberFuture * Deletes a member from a converstion. diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/package-info.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/package-info.java similarity index 96% rename from libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/package-info.java rename to libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/package-info.java index e57157f5f..86fe999a4 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/implementation/package-info.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/package-info.java @@ -22,4 +22,4 @@ * Generate your own from the [Connector API Swagger file](https://raw.githubusercontent.com/Microsoft/BotBuilder/master/CSharp/Library/Microsoft.Bot.Connector.Shared/Swagger/ConnectorAPI.json) © 2016 Microsoft. */ -package com.microsoft.bot.connector.implementation; +package com.microsoft.bot.connector.rest; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAccessTokenStub.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAccessTokenStub.java index 2f62336b7..cf4a977cb 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAccessTokenStub.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAccessTokenStub.java @@ -1,13 +1,7 @@ package com.microsoft.bot.connector; import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; -import com.microsoft.bot.schema.models.TokenResponse; -import com.microsoft.rest.credentials.ServiceClientCredentials; import okhttp3.OkHttpClient; -import okhttp3.Response; - - -import static java.util.concurrent.CompletableFuture.completedFuture; public class BotAccessTokenStub extends MicrosoftAppCredentials { private final String token; @@ -26,8 +20,4 @@ public BotAccessTokenStub(String token, String appId, String appSecret) { public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) { clientBuilder.interceptors().add(new TestBearerTokenInterceptor(this.token)); } - - - - } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java deleted file mode 100644 index 7bf891017..000000000 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotAuthenticatorTest.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.microsoft.bot.connector; - -import com.microsoft.aad.adal4j.AuthenticationException; -import com.microsoft.bot.connector.authentication.*; -import com.microsoft.bot.schema.models.Activity; -import okhttp3.Request; -import org.junit.Assert; -import org.junit.Test; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.concurrent.ExecutionException; - -public class BotAuthenticatorTest { - - private static final String AppId = "2cd87869-38a0-4182-9251-d056e8f0ac24"; - private static final String AppPassword = "2.30Vs3VQLKt974F"; - - @Test - public void ConnectorAuthHeaderCorrectAppIdAndServiceUrlShouldValidate() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl(AppId, ""); - ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(header, credentials, "", "https://webchat.botframework.com/").get(); - - Assert.assertTrue(identity.isAuthenticated()); - } - - @Test - public void ConnectorAuthHeaderBotAppIdDiffersShouldNotValidate() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl("00000000-0000-0000-0000-000000000000", ""); - - try { - JwtTokenValidation.validateAuthHeader(header, credentials, "", null).get(); - } catch (AuthenticationException e) { - Assert.assertTrue(e.getMessage().contains("Invalid AppId passed on token")); - } - } - - @Test - public void ConnectorAuthHeaderBotWithNoCredentialsShouldNotValidate() throws IOException, ExecutionException, InterruptedException { - // token received and auth disabled - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl("", ""); - - try { - JwtTokenValidation.validateAuthHeader(header, credentials, "", null).get(); - } catch (AuthenticationException e) { - Assert.assertTrue(e.getMessage().contains("Invalid AppId passed on token")); - } - } - - @Test - public void EmptyHeaderBotWithNoCredentialsShouldThrow() throws ExecutionException, InterruptedException { - String header = ""; - CredentialProvider credentials = new CredentialProviderImpl("", ""); - - try { - JwtTokenValidation.validateAuthHeader(header, credentials, "", null).get(); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().contains("authHeader")); - } - } - - @Test - public void EmulatorMsaHeaderCorrectAppIdAndServiceUrlShouldValidate() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl(AppId, ""); - ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(header, credentials, "", "https://webchat.botframework.com/").get(); - - Assert.assertTrue(identity.isAuthenticated()); - } - - @Test - public void EmulatorMsaHeaderBotAppIdDiffersShouldNotValidate() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl("00000000-0000-0000-0000-000000000000", ""); - - try { - JwtTokenValidation.validateAuthHeader(header, credentials, "", null).get(); - } catch (AuthenticationException e) { - Assert.assertTrue(e.getMessage().contains("Invalid AppId passed on token")); - } - } - - /** - * Tests with a valid Token and service url; and ensures that Service url is added to Trusted service url list. - */ - @Test - public void ChannelMsaHeaderValidServiceUrlShouldBeTrusted() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl(AppId, ""); - JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"), - header, - credentials); - - Assert.assertTrue(MicrosoftAppCredentials.isTrustedServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/")); - } - - /** - * Tests with a valid Token and invalid service url; and ensures that Service url is NOT added to Trusted service url list. - */ - @Test - public void ChannelMsaHeaderInvalidServiceUrlShouldNotBeTrusted() throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - CredentialProvider credentials = new CredentialProviderImpl("7f74513e-6f96-4dbc-be9d-9a81fea22b88", ""); - - try { - JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://webchat.botframework.com/"), - header, - credentials); - Assert.fail("Should have thrown AuthenticationException"); - } catch (AuthenticationException ex) { - Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); - } - - } - - /** - * Tests with no authentication header and makes sure the service URL is not added to the trusted list. - */ - @Test - public void ChannelAuthenticationDisabledShouldBeAnonymous() throws ExecutionException, InterruptedException { - String header = ""; - CredentialProvider credentials = new CredentialProviderImpl("", ""); - - ClaimsIdentity identity = JwtTokenValidation.authenticateRequest(new Activity().withServiceUrl("https://webchat.botframework.com/"), header, credentials).get(); - Assert.assertEquals("anonymous", identity.getIssuer()); - } - - /** - * Tests with no authentication header and makes sure the service URL is not added to the trusted list. - */ - @Test - public void ChannelAuthenticationDisabledServiceUrlShouldNotBeTrusted() throws ExecutionException, InterruptedException { - String header = ""; - CredentialProvider credentials = new CredentialProviderImpl("", ""); - - ClaimsIdentity identity = JwtTokenValidation.authenticateRequest(new Activity().withServiceUrl("https://webchat.botframework.com/"), header, credentials).get(); - Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); - } - - private static String getHeaderToken() throws MalformedURLException, ExecutionException, InterruptedException { - return String.format("Bearer %s", new MicrosoftAppCredentials(AppId, AppPassword).getToken().get().getAccessToken()); - } -} diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java index bc8e41aa3..9f1ff581b 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java @@ -1,12 +1,12 @@ package com.microsoft.bot.connector; import com.microsoft.bot.connector.base.TestBase; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.models.ChannelAccount; import com.microsoft.rest.RestClient; public class BotConnectorTestBase extends TestBase { - protected ConnectorClientImpl connector; + protected RestConnectorClient connector; protected ChannelAccount bot; protected ChannelAccount user; @@ -20,7 +20,7 @@ public BotConnectorTestBase(RunCondition runCondition) { @Override protected void initializeClients(RestClient restClient, String botId, String userId) { - connector = new ConnectorClientImpl(restClient); + connector = new RestConnectorClient(restClient); bot = new ChannelAccount().withId(botId); user = new ChannelAccount().withId(userId); } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java index 97f03d82c..0e5cb6982 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java @@ -1,6 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector; -import com.microsoft.bot.connector.models.ErrorResponseException; +import com.microsoft.bot.connector.rest.ErrorResponseException; import com.microsoft.bot.schema.models.*; import org.junit.Assert; import org.junit.Test; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EndorsementsValidatorTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EndorsementsValidatorTests.java index 52875b9c2..b01fc078a 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EndorsementsValidatorTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EndorsementsValidatorTests.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector; import com.microsoft.bot.connector.authentication.EndorsementsValidator; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index c5d4da348..749fc8a40 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -1,29 +1,412 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector; -import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; -import com.microsoft.bot.connector.authentication.SimpleCredentialProvider; +import com.microsoft.aad.adal4j.AuthenticationException; +import com.microsoft.bot.connector.authentication.*; +import com.microsoft.bot.schema.models.Activity; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; +import java.io.IOException; import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; public class JwtTokenValidationTests { + + private static final String APPID = "2cd87869-38a0-4182-9251-d056e8f0ac24"; + private static final String APPPASSWORD = "2.30Vs3VQLKt974F"; + + private static String getHeaderToken() throws MalformedURLException, ExecutionException, InterruptedException { + return String.format("Bearer %s", new MicrosoftAppCredentials(APPID, APPPASSWORD).getToken().get().getAccessToken()); + } + + @Test + public void ConnectorAuthHeaderCorrectAppIdAndServiceUrlShouldValidate() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider(APPID, ""); + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + "https://webchat.botframework.com/").join(); + + Assert.assertTrue(identity.isAuthenticated()); + } + + @Test + public void Connector_AuthHeader_CorrectAppIdAndServiceUrl_WithGovChannelService_ShouldValidate() throws IOException, ExecutionException, InterruptedException { + JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds( + APPID, + APPPASSWORD, + GovernmentAuthenticationConstants.CHANNELSERVICE + ); + } + + @Test + public void ConnectorAuthHeaderBotAppIdDiffersShouldNotValidate() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider("00000000-0000-0000-0000-000000000000", ""); + + try { + JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + null).join(); + } catch (CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void ConnectorAuthHeaderBotWithNoCredentialsShouldNotValidate() throws IOException, ExecutionException, InterruptedException { + // token received and auth disabled + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider("", ""); + + try { + JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + null).join(); + } catch (CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void EmptyHeaderBotWithNoCredentialsShouldThrow() throws ExecutionException, InterruptedException { + String header = ""; + CredentialProvider credentials = new SimpleCredentialProvider("", ""); + + try { + JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + null).join(); + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains("authHeader")); + } + } + + @Test + public void EmulatorMsaHeaderCorrectAppIdAndServiceUrlShouldValidate() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider(APPID, ""); + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + "https://webchat.botframework.com/").join(); + + Assert.assertTrue(identity.isAuthenticated()); + } + + @Test + public void EmulatorMsaHeaderBotAppIdDiffersShouldNotValidate() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider("00000000-0000-0000-0000-000000000000", ""); + + try { + JwtTokenValidation.validateAuthHeader( + header, + credentials, + new SimpleChannelProvider(), + "", + null).join(); + } catch (CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void Emulator_AuthHeader_CorrectAppIdAndServiceUrl_WithGovChannelService_ShouldValidate() throws IOException, ExecutionException, InterruptedException { + JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds( + "2cd87869-38a0-4182-9251-d056e8f0ac24", // emulator creds + "2.30Vs3VQLKt974F", + GovernmentAuthenticationConstants.CHANNELSERVICE); + } + + @Test + public void Emulator_AuthHeader_CorrectAppIdAndServiceUrl_WithPrivateChannelService_ShouldValidate() throws IOException, ExecutionException, InterruptedException { + JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds( + "2cd87869-38a0-4182-9251-d056e8f0ac24", // emulator creds + "2.30Vs3VQLKt974F", + "TheChannel"); + } + + /** + * Tests with a valid Token and service url; and ensures that Service url is added to Trusted service url list. + */ + @Test + public void ChannelMsaHeaderValidServiceUrlShouldBeTrusted() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider(APPID, ""); + JwtTokenValidation.authenticateRequest( + new Activity().withServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"), + header, + credentials, + new SimpleChannelProvider()).join(); + + Assert.assertTrue(MicrosoftAppCredentials.isTrustedServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/")); + } + + /** + * Tests with a valid Token and invalid service url; and ensures that Service url is NOT added to Trusted service url list. + */ + @Test + public void ChannelMsaHeaderInvalidServiceUrlShouldNotBeTrusted() throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + CredentialProvider credentials = new SimpleCredentialProvider("7f74513e-6f96-4dbc-be9d-9a81fea22b88", ""); + + try { + JwtTokenValidation.authenticateRequest( + new Activity().withServiceUrl("https://webchat.botframework.com/"), + header, + credentials, + new SimpleChannelProvider()).join(); + Assert.fail("Should have thrown AuthenticationException"); + } catch (CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); + } + } + + /** + * Tests with no authentication header and makes sure the service URL is not added to the trusted list. + */ + @Test + public void ChannelAuthenticationDisabledShouldBeAnonymous() throws ExecutionException, InterruptedException { + String header = ""; + CredentialProvider credentials = new SimpleCredentialProvider("", ""); + + ClaimsIdentity identity = JwtTokenValidation.authenticateRequest( + new Activity().withServiceUrl("https://webchat.botframework.com/"), + header, + credentials, + new SimpleChannelProvider()).join(); + Assert.assertEquals("anonymous", identity.getIssuer()); + } + + /** + * Tests with no authentication header and makes sure the service URL is not added to the trusted list. + */ @Test - public void Connector_AuthHeader_CorrectAppIdAndServiceUrl_ShouldValidate() - throws MalformedURLException, ExecutionException, InterruptedException { - - MicrosoftAppCredentials credentials = new MicrosoftAppCredentials( - "2cd87869-38a0-4182-9251-d056e8f0ac24", - "2.30Vs3VQLKt974F"); - -// String header = "Bearer " + credentials.getToken().get().getAccessToken(); -// SimpleCredentialProvider credentials = new SimpleCredentialProvider( -// "2cd87869-38a0-4182-9251-d056e8f0ac24", -// null); -// -// JwtTokenValidation.ValidateAuthHeader(header, credentials, new SimpleChannelProvider(), null, "https://webchat.botframework.com/", client); - // - // Assert.True(result.IsAuthenticated); + public void ChannelAuthenticationDisabledServiceUrlShouldNotBeTrusted() throws ExecutionException, InterruptedException { + String header = ""; + CredentialProvider credentials = new SimpleCredentialProvider("", ""); + + ClaimsIdentity identity = JwtTokenValidation.authenticateRequest( + new Activity().withServiceUrl("https://webchat.botframework.com/"), + header, + credentials, + new SimpleChannelProvider()).join(); + Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); + } + + @Test + public void EnterpriseChannelValidation_Succeeds() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + } catch (Exception e) { + Assert.fail("Should not have thrown " + e.getCause().getClass().getName()); + } + } + + @Test + public void EnterpriseChannelValidation_NoAuthentication_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity(null, claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (Exception e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void EnterpriseChannelValidation_NoAudienceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (Exception e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void EnterpriseChannelValidation_WrongAudienceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (Exception e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void GovernmentChannelValidation_Succeeds() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.assertTrue(true); + } catch(Exception e) { + Assert.fail("Should not have thrown " + e.getCause().getClass().getName()); + } + } + + @Test + public void GovernmentChannelValidation_NoAuthentication_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity(null, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch(CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + @Test + public void GovernmentChannelValidation_WrongAudienceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity(null, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch(CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + + /* + @Test + public void GovernmentChannelValidation_WrongAudienceClaimIssuer_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap<>(); + claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + ClaimsIdentity identity = new ClaimsIdentity(null, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch(CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + } + */ + + private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String appId, String pwd, String channelService) throws IOException, ExecutionException, InterruptedException { + String header = getHeaderToken(); + JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(header, appId, pwd, channelService); + } + + private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String header, String appId, String pwd, String channelService) { + CredentialProvider credentials = new SimpleCredentialProvider(appId, pwd); + ChannelProvider channel = new SimpleChannelProvider(channelService); + + try { + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader( + header, + credentials, + channel, + "", + "https://webchat.botframework.com/").join(); + + Assert.assertTrue(identity.isAuthenticated()); + } catch(Exception e) { + Assert.fail("Should not have thrown " + e.getClass().getName()); + } + } + + private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Throws(String header, String appId, String pwd, String channelService) throws ExecutionException, InterruptedException { + CredentialProvider credentials = new SimpleCredentialProvider(appId, pwd); + ChannelProvider channel = new SimpleChannelProvider(channelService); + + try { + JwtTokenValidation.validateAuthHeader( + header, + credentials, + channel, + "", + "https://webchat.botframework.com/").join(); + Assert.fail("Should have thrown AuthenticationException"); + } catch (AuthenticationException e) { + Assert.assertTrue(true); + } } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTest.java index 0c9d229c6..6c0069b6d 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthConnectorTest.java @@ -1,33 +1,21 @@ package com.microsoft.bot.connector; -import com.microsoft.aad.adal4j.ClientCredential; import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; import com.microsoft.bot.connector.authentication.OAuthClient; -import com.microsoft.bot.connector.base.TestBase; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; -import com.microsoft.bot.schema.models.TokenResponse; -import com.microsoft.rest.RestClient; -import org.apache.commons.lang3.StringUtils; +import com.microsoft.bot.connector.rest.RestConnectorClient; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static java.util.concurrent.CompletableFuture.completedFuture; - - public class OAuthConnectorTest extends OAuthTestBase { - private ConnectorClientImpl mockConnectorClient; + private RestConnectorClient mockConnectorClient; private MicrosoftAppCredentials credentials; public OAuthConnectorTest() throws IOException, ExecutionException, InterruptedException, URISyntaxException { diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java index 8a5ac123c..1aaa5a68d 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java @@ -5,22 +5,17 @@ import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; import com.microsoft.bot.connector.authentication.OAuthClient; import com.microsoft.bot.connector.base.TestBase; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.models.ChannelAccount; import com.microsoft.rest.RestClient; -import okhttp3.Request; -import org.apache.commons.io.FileSystemUtils; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Function; -import static java.util.concurrent.CompletableFuture.completedFuture; - public class OAuthTestBase extends TestBase { @@ -32,7 +27,7 @@ public class OAuthTestBase extends TestBase private String token; - protected ConnectorClientImpl connector; + protected RestConnectorClient connector; private ChannelAccount bot; public ChannelAccount getBot() { @@ -70,7 +65,7 @@ protected void initializeClients(RestClient restClient, String botId, String use } } - this.connector = new ConnectorClientImpl(restClient); + this.connector = new RestConnectorClient(restClient); if (this.clientId != null && this.clientSecret != null) { MicrosoftAppCredentials credentials = new MicrosoftAppCredentials(this.clientId, this.clientSecret); @@ -116,7 +111,7 @@ public CompletableFuture UseOAuthClientFor(Function{ OAuthClient oauthClient = null; try { - oauthClient = new OAuthClient(this.connector, AuthenticationConstants.OAuthUrl); + oauthClient = new OAuthClient(this.connector, AuthenticationConstants.OAUTH_URL); } catch (URISyntaxException e) { e.printStackTrace(); } catch (MalformedURLException e) { diff --git a/libraries/bot-integration-core/pom.xml b/libraries/bot-integration-core/pom.xml new file mode 100644 index 000000000..64233d8a4 --- /dev/null +++ b/libraries/bot-integration-core/pom.xml @@ -0,0 +1,207 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-integration-core + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Integration Core + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + org.slf4j + slf4j-api + + + com.microsoft.bot + bot-schema + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-connector + 4.0.0-SNAPSHOT + + + org.slf4j + slf4j-api + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-connector + xml + 256m + + true + + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java new file mode 100644 index 000000000..f3b3182a1 --- /dev/null +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java @@ -0,0 +1,30 @@ +package com.microsoft.bot.integration; + +import java.io.IOException; +import java.util.Properties; +import org.slf4j.LoggerFactory; + +/** + * Provides access to properties defined in a Properties file located on the classpath. + */ +public class ClasspathPropertiesConfiguration implements Configuration { + private Properties properties; + + /** + * Loads properties from the 'application.properties' file. + * @throws IOException + */ + public ClasspathPropertiesConfiguration() { + try { + properties = new Properties(); + properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties")); + } + catch (IOException e) { + (LoggerFactory.getLogger(ClasspathPropertiesConfiguration.class)).error("Unable to load properties", e); + } + } + + public String getProperty(String key) { + return properties.getProperty(key); + } +} diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java new file mode 100644 index 000000000..9a98516da --- /dev/null +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.integration; + +/** + * Provides read-only access to configuration properties. + */ +public interface Configuration { + String getProperty(String key); +} diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java new file mode 100644 index 000000000..08054285a --- /dev/null +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.integration; + +import com.microsoft.bot.connector.authentication.SimpleChannelProvider; + +/** + * Channel provider which uses Configuration to lookup the channel service property. + * + * This will populate the SimpleChannelProvider.ChannelService from a configuration entry with + * the key of "ChannelService". + */ +public class ConfigurationChannelProvider extends SimpleChannelProvider { + public ConfigurationChannelProvider(Configuration configuration) { + super(configuration.getProperty("ChannelService")); + } +} diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java new file mode 100644 index 000000000..7750309bf --- /dev/null +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.integration; + +import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; +import com.microsoft.bot.connector.authentication.SimpleCredentialProvider; + +/** + * Credential provider which uses Configuration to lookup appId and password. + */ +public class ConfigurationCredentialProvider extends SimpleCredentialProvider { + public ConfigurationCredentialProvider(Configuration configuration) { + setAppId(configuration.getProperty(MicrosoftAppCredentials.MICROSOFTAPPID)); + setPassword(configuration.getProperty(MicrosoftAppCredentials.MICROSOFTAPPPASSWORD)); + } +} diff --git a/pom.xml b/pom.xml index 43ec2dfd9..9e5cb3a2b 100644 --- a/pom.xml +++ b/pom.xml @@ -130,6 +130,7 @@ libraries/bot-schema libraries/bot-builder libraries/bot-connector + libraries/bot-integration-core samples/bot-connector-sample samples/servlet-echo samples/spring-echo diff --git a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java index 9fa813525..9e626450a 100644 --- a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java +++ b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java @@ -6,11 +6,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.microsoft.aad.adal4j.AuthenticationException; -import com.microsoft.bot.connector.authentication.CredentialProvider; -import com.microsoft.bot.connector.authentication.CredentialProviderImpl; -import com.microsoft.bot.connector.authentication.JwtTokenValidation; -import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.ConnectorClient; +import com.microsoft.bot.connector.authentication.*; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ActivityTypes; import com.microsoft.bot.schema.models.ResourceResponse; @@ -30,7 +28,7 @@ public class App { private static String appPassword = ""; // <-- app password --> public static void main( String[] args ) throws IOException { - CredentialProvider credentialProvider = new CredentialProviderImpl(appId, appPassword); + CredentialProvider credentialProvider = new SimpleCredentialProvider(appId, appPassword); HttpServer server = HttpServer.create(new InetSocketAddress(3978), 0); server.createContext("/api/messages", new MessageHandle(credentialProvider)); server.setExecutor(null); @@ -55,7 +53,7 @@ public void handle(HttpExchange httpExchange) throws IOException { Activity activity = getActivity(httpExchange); String authHeader = httpExchange.getRequestHeaders().getFirst("Authorization"); try { - JwtTokenValidation.authenticateRequest(activity, authHeader, credentialProvider); + JwtTokenValidation.authenticateRequest(activity, authHeader, credentialProvider, new SimpleChannelProvider()); // send ack to user activity httpExchange.sendResponseHeaders(202, 0); @@ -63,7 +61,7 @@ public void handle(HttpExchange httpExchange) throws IOException { if (activity.type().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text - ConnectorClientImpl connector = new ConnectorClientImpl(activity.serviceUrl(), this.credentials); + ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), this.credentials); ResourceResponse response = connector.conversations().sendToConversation(activity.conversation().id(), new Activity() .withType(ActivityTypes.MESSAGE) diff --git a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java index e8547fb03..2ff5b49bf 100644 --- a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java +++ b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java @@ -8,12 +8,9 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.microsoft.aad.adal4j.AuthenticationException; -import com.microsoft.bot.connector.authentication.ClaimsIdentity; -import com.microsoft.bot.connector.authentication.CredentialProvider; -import com.microsoft.bot.connector.authentication.CredentialProviderImpl; -import com.microsoft.bot.connector.authentication.JwtTokenValidation; -import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.ConnectorClient; +import com.microsoft.bot.connector.authentication.*; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ActivityTypes; import javax.servlet.*; @@ -53,7 +50,7 @@ public void init() throws ServletException { String appId = p.getProperty("MicrosoftAppId"); String appPassword = p.getProperty("MicrosoftAppPassword"); - this.credentialProvider = new CredentialProviderImpl(appId, appPassword); + this.credentialProvider = new SimpleCredentialProvider(appId, appPassword); this.credentials = new MicrosoftAppCredentials(appId, appPassword); } catch(IOException ioe){ @@ -67,11 +64,11 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) final Activity activity = getActivity(request); String authHeader = request.getHeader("Authorization"); - CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, credentialProvider); + CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, credentialProvider, new SimpleChannelProvider()); authenticateRequest.thenRunAsync(() -> { if (activity.type().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text - ConnectorClientImpl connector = new ConnectorClientImpl(activity.serviceUrl(), this.credentials); + ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), this.credentials); connector.conversations().sendToConversation(activity.conversation().id(), new Activity() .withType(ActivityTypes.MESSAGE) diff --git a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java index bbabda0de..2591a012a 100644 --- a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java +++ b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java @@ -2,6 +2,8 @@ // Licensed under the MIT License. package com.microsoft.bot.sample.spring; +import com.microsoft.bot.connector.ConnectorClient; +import com.microsoft.bot.connector.authentication.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -15,12 +17,7 @@ import javax.annotation.PostConstruct; import com.microsoft.aad.adal4j.AuthenticationException; -import com.microsoft.bot.connector.authentication.ClaimsIdentity; -import com.microsoft.bot.connector.authentication.CredentialProvider; -import com.microsoft.bot.connector.authentication.CredentialProviderImpl; -import com.microsoft.bot.connector.authentication.JwtTokenValidation; -import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; -import com.microsoft.bot.connector.implementation.ConnectorClientImpl; +import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ActivityTypes; @@ -51,7 +48,7 @@ public class BotController { */ @PostConstruct public void init() { - _credentialProvider = new CredentialProviderImpl(appId, appPassword); + _credentialProvider = new SimpleCredentialProvider(appId, appPassword); _credentials = new MicrosoftAppCredentials(appId, appPassword); } @@ -66,13 +63,13 @@ public void init() { public ResponseEntity incoming(@RequestBody Activity activity, @RequestHeader(value = "Authorization", defaultValue = "") String authHeader) { try { - CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, _credentialProvider); + CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, _credentialProvider, new SimpleChannelProvider()); authenticateRequest.thenRunAsync(() -> { if (activity.type().equals(ActivityTypes.MESSAGE)) { logger.info("Received: " + activity.text()); // reply activity with the same text - ConnectorClientImpl connector = new ConnectorClientImpl(activity.serviceUrl(), _credentials); + ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), _credentials); connector.conversations().sendToConversation(activity.conversation().id(), new Activity().withType(ActivityTypes.MESSAGE).withText("Echo: " + activity.text()) .withRecipient(activity.from()).withFrom(activity.recipient())); From 2ff8d4734376e7415bcd2f9cc46525d236634c26 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 09:19:12 -0500 Subject: [PATCH 04/26] Fixed JwtTokenValidation.authenticateRequest. Removed unneeded throw declarations from CompletableFuture returning methods. --- .../authentication/ChannelValidation.java | 32 +++++++-- .../authentication/EmulatorValidation.java | 14 ++-- .../EnterpriseChannelValidation.java | 14 ++-- .../GovernmentChannelValidation.java | 13 +++- .../authentication/JwtTokenValidation.java | 66 +++++++++++-------- .../MicrosoftAppCredentials.java | 1 - .../bot/sample/servlet/EchoServlet.java | 19 ++++-- .../bot/sample/spring/BotController.java | 33 ++++++---- 8 files changed, 125 insertions(+), 67 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index 1540f75d7..4c39a9977 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -13,24 +13,38 @@ public class ChannelValidation { /** * TO BOT FROM CHANNEL: Token validation parameters when connecting to a bot */ - public static final TokenValidationParameters ToBotFromChannelTokenValidationParameters = TokenValidationParameters.toBotFromChannelTokenValidationParameters(); + public static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = TokenValidationParameters.toBotFromChannelTokenValidationParameters(); /** * Validate the incoming Auth Header as a token sent from the Bot Framework Service. * - * @param authHeader The raw HTTP header in the format: "Bearer [longString]" + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". * @param credentials The user defined set of valid credentials, such as the AppId. * @param channelId ChannelId for endorsements validation. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId) { return authenticateToken(authHeader, credentials, channelId, new AuthenticationConfiguration()); } - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + /** + * Validate the incoming Auth Header as a token sent from the Bot Framework Service. + * + * @param authHeader The raw HTTP header in the format: "Bearer [longString]". + * @param credentials The user defined set of valid credentials, such as the AppId. + * @param channelId ChannelId for endorsements validation. + * @param authConfig The AuthenticationConfiguration. + * @return A valid ClaimsIdentity. + * + * On join: + * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. + */ + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, AuthenticationConfiguration authConfig) { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( - ToBotFromChannelTokenValidationParameters, + TOKENVALIDATIONPARAMETERS, AuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, AuthenticationConstants.AllowedSigningAlgorithms); @@ -84,9 +98,11 @@ public static CompletableFuture authenticateToken(String authHea * @param channelId ChannelId for endorsements validation. * @param serviceUrl Service url. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) { return authenticateToken(authHeader, credentials, channelId, serviceUrl, new AuthenticationConfiguration()); } @@ -99,9 +115,11 @@ public static CompletableFuture authenticateToken(String authHea * @param serviceUrl Service url. * @param authConfig The authentication configuration. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) { return ChannelValidation.authenticateToken(authHeader, credentials, channelId, authConfig) .thenApply(identity -> { if (!identity.claims().containsKey(AuthenticationConstants.SERVICE_URL_CLAIM)) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index 7e7aaac77..561070c0f 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -18,7 +18,7 @@ public class EmulatorValidation { /** * TO BOT FROM EMULATOR: Token validation parameters when connecting to a channel. */ - private static final TokenValidationParameters ToBotFromEmulatorTokenValidationParameters = TokenValidationParameters.toBotFromEmulatorTokenValidationParameters(); + private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = TokenValidationParameters.toBotFromEmulatorTokenValidationParameters(); /** * Determines if a given Auth header is from the Bot Framework Emulator @@ -59,7 +59,7 @@ public static Boolean isTokenFromEmulator(String authHeader) { // Is the token issues by a source we consider to be the emulator? // Not a Valid Issuer. This is NOT a Bot Framework Emulator Token. - return ToBotFromEmulatorTokenValidationParameters.validIssuers.contains(decodedJWT.getIssuer()); + return TOKENVALIDATIONPARAMETERS.validIssuers.contains(decodedJWT.getIssuer()); } /** @@ -71,9 +71,11 @@ public static Boolean isTokenFromEmulator(String authHeader) { * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. * @param channelId The ID of the channel to validate. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId) { return authenticateToken(authHeader, credentials, channelProvider, channelId, new AuthenticationConfiguration()); } @@ -87,15 +89,17 @@ public static CompletableFuture authenticateToken(String authHea * @param channelId The ID of the channel to validate. * @param authConfig The authentication configuration. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) { String openIdMetadataUrl = channelProvider != null && channelProvider.isGovernment() ? GovernmentAuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL : AuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL; JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( - ToBotFromEmulatorTokenValidationParameters, + TOKENVALIDATIONPARAMETERS, openIdMetadataUrl, AuthenticationConstants.AllowedSigningAlgorithms); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index 4c1264add..a085045aa 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -12,7 +12,7 @@ import java.util.concurrent.ExecutionException; public class EnterpriseChannelValidation { - private static final TokenValidationParameters ENTERPRISE_VALIDATION_PARAMETERS = new TokenValidationParameters() {{ + private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ this.validateIssuer = true; this.validIssuers = new ArrayList() {{ add(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); @@ -32,9 +32,11 @@ public class EnterpriseChannelValidation { * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. * @param channelId The ID of the channel to validate. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId) { return authenticateToken(authHeader, credentials, channelProvider, serviceUrl, channelId, new AuthenticationConfiguration()); } @@ -48,18 +50,20 @@ public static CompletableFuture authenticateToken(String authHea * @param channelId The ID of the channel to validate. * @param authConfig The authentication configuration. * @return A valid ClaimsIdentity. + * + * On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) { if (authConfig == null) { - throw new AuthenticationException("Missing AuthenticationConfiguration"); + throw new IllegalArgumentException("Missing AuthenticationConfiguration"); } return channelProvider.getChannelService() .thenCompose(channelService -> { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( - ENTERPRISE_VALIDATION_PARAMETERS, + TOKENVALIDATIONPARAMETERS, String.format(AuthenticationConstants.TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT, channelService), AuthenticationConstants.AllowedSigningAlgorithms); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java index e4e18e5c1..c10d52b10 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java @@ -15,7 +15,7 @@ * TO BOT FROM GOVERNMENT CHANNEL: Token validation parameters when connecting to a bot. */ public class GovernmentChannelValidation { - private static final TokenValidationParameters GOVERNMENT_VALIDATION_PARAMETERS = new TokenValidationParameters() {{ + private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ this.validateIssuer = true; this.validIssuers = new ArrayList() {{ add(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); @@ -34,6 +34,9 @@ public class GovernmentChannelValidation { * @param serviceUrl The service url from the request. * @param channelId The ID of the channel to validate. * @return A CompletableFuture representing the asynchronous operation. + * + * On join: + * @throws AuthenticationException Authentication failed. */ public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId) { return authenticateToken(authHeader, credentials, serviceUrl, channelId, new AuthenticationConfiguration()); @@ -48,10 +51,13 @@ public static CompletableFuture authenticateToken(String authHea * @param channelId The ID of the channel to validate. * @param authConfig The authentication configuration. * @return A CompletableFuture representing the asynchronous operation. + * + * On join: + * @throws AuthenticationException Authentication failed. */ public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( - GOVERNMENT_VALIDATION_PARAMETERS, + TOKENVALIDATIONPARAMETERS, GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, AuthenticationConstants.AllowedSigningAlgorithms); @@ -68,6 +74,9 @@ public static CompletableFuture authenticateToken(String authHea * @param credentials The user defined set of valid credentials, such as the AppId. * @param serviceUrl The service url from the request. * @return A CompletableFuture representing the asynchronous operation. + * + * On join: + * @throws AuthenticationException Validation failed. */ public static CompletableFuture validateIdentity(ClaimsIdentity identity, CredentialProvider credentials, String serviceUrl) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 0398d97b5..90fa8c672 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -10,6 +10,9 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +/** + * Contains helper methods for authenticating incoming HTTP requests. + */ public class JwtTokenValidation { /** @@ -36,30 +39,31 @@ public static CompletableFuture authenticateRequest(Activity act * @throws AuthenticationException Throws on auth failed. */ public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, AuthenticationConfiguration authConfig) throws AuthenticationException, InterruptedException, ExecutionException { - if (StringUtils.isEmpty(authHeader)) { - // No auth header was sent. We might be on the anonymous code path. - boolean isAuthDisable = credentials.isAuthenticationDisabledAsync().get(); - if (isAuthDisable) { - // In the scenario where Auth is disabled, we still want to have the - // IsAuthenticated flag set in the ClaimsIdentity. To do this requires - // adding in an empty claim. - return CompletableFuture.completedFuture(new ClaimsIdentity("anonymous")); + return CompletableFuture.supplyAsync(() -> { + if (StringUtils.isEmpty(authHeader)) { + // No auth header was sent. We might be on the anonymous code path. + boolean isAuthDisable = credentials.isAuthenticationDisabledAsync().join(); + if (isAuthDisable) { + // In the scenario where Auth is disabled, we still want to have the + // IsAuthenticated flag set in the ClaimsIdentity. To do this requires + // adding in an empty claim. + return new ClaimsIdentity("anonymous"); + } + + // No Auth Header. Auth is required. Request is not authorized. + CompletableFuture result = CompletableFuture.completedFuture(null); + throw new AuthenticationException("No Auth Header. Auth is required."); } - // No Auth Header. Auth is required. Request is not authorized. - CompletableFuture result = CompletableFuture.completedFuture(null); - result.completeExceptionally(new AuthenticationException("No Auth Header. Auth is required.")); - return result; - } + // Go through the standard authentication path. This will throw AuthenticationException if + // it fails. + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.channelId(), activity.serviceUrl(), authConfig).join(); - // Go through the standard authentication path. - return JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.channelId(), activity.serviceUrl(), authConfig) - .thenApply(identity -> { - // On the standard Auth path, we need to trust the URL that was incoming. - MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); + // On the standard Auth path, we need to trust the URL that was incoming. + MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); - return identity; - }); + return identity; + }); } /** @@ -71,11 +75,14 @@ public static CompletableFuture authenticateRequest(Activity act * @param channelId The ID of the channel that sent the request. * @param serviceUrl The service URL for the activity. * @return A task that represents the work queued to execute. - * @throws ExecutionException - * @throws InterruptedException - * @throws AuthenticationException + * + * On Call: + * @throws IllegalArgumentException Incorrect arguments supplied + * + * On join: + * @throws AuthenticationException Authentication Error */ - public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl) { return validateAuthHeader(authHeader, credentials, channelProvider, channelId, serviceUrl, new AuthenticationConfiguration()); } @@ -89,11 +96,14 @@ public static CompletableFuture validateAuthHeader(String authHe * @param serviceUrl The service URL for the activity. * @param authConfig The authentication configuration. * @return A task that represents the work queued to execute. - * @throws ExecutionException - * @throws InterruptedException - * @throws AuthenticationException + * + * On Call: + * @throws IllegalArgumentException Incorrect arguments supplied + * + * On Join: + * @throws AuthenticationException Authentication Error */ - public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) throws ExecutionException, InterruptedException, AuthenticationException { + public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) { if (StringUtils.isEmpty(authHeader)) { throw new IllegalArgumentException("No authHeader present. Auth is required."); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index d958a89a1..a62a2723d 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -28,7 +28,6 @@ public class MicrosoftAppCredentials implements ServiceClientCredentials { public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - public static final MediaType FORM_ENCODE = MediaType.parse("application/x-www-form-urlencoded"); private static ConcurrentMap trustHostNames = new ConcurrentHashMap<>(); static { diff --git a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java index 2ff5b49bf..aa7130b29 100644 --- a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java +++ b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.util.concurrent.CompletableFuture; import java.util.Properties; +import java.util.concurrent.CompletionException; import java.util.logging.Level; import java.util.logging.Logger; @@ -77,13 +78,21 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .withFrom(activity.recipient()) ); } - }); - } catch (AuthenticationException ex) { - response.setStatus(401); - LOGGER.log(Level.WARNING, "Auth failed!", ex); + }).join(); + + response.setStatus(200); + } catch (CompletionException ex) { + if (ex.getCause() instanceof AuthenticationException) { + LOGGER.log(Level.WARNING, "Auth failed!", ex); + response.setStatus(401); + } + else { + LOGGER.log(Level.WARNING, "Execution failed", ex); + response.setStatus(500); + } } catch (Exception ex) { - response.setStatus(500); LOGGER.log(Level.WARNING, "Execution failed", ex); + response.setStatus(500); } } diff --git a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java index 2591a012a..fa4c85aa9 100644 --- a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java +++ b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java @@ -21,7 +21,7 @@ import com.microsoft.bot.schema.models.Activity; import com.microsoft.bot.schema.models.ActivityTypes; -import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; /** * This is the controller that will receive incoming Channel Activity messages. @@ -63,20 +63,25 @@ public void init() { public ResponseEntity incoming(@RequestBody Activity activity, @RequestHeader(value = "Authorization", defaultValue = "") String authHeader) { try { - CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, _credentialProvider, new SimpleChannelProvider()); - authenticateRequest.thenRunAsync(() -> { - if (activity.type().equals(ActivityTypes.MESSAGE)) { - logger.info("Received: " + activity.text()); + JwtTokenValidation.authenticateRequest(activity, authHeader, _credentialProvider, new SimpleChannelProvider()) + .thenRunAsync(() -> { + if (activity.type().equals(ActivityTypes.MESSAGE)) { + logger.info("Received: " + activity.text()); - // reply activity with the same text - ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), _credentials); - connector.conversations().sendToConversation(activity.conversation().id(), - new Activity().withType(ActivityTypes.MESSAGE).withText("Echo: " + activity.text()) - .withRecipient(activity.from()).withFrom(activity.recipient())); - } - }); - } catch (AuthenticationException ex) { - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + // reply activity with the same text + ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), _credentials); + connector.conversations().sendToConversation(activity.conversation().id(), + new Activity().withType(ActivityTypes.MESSAGE).withText("Echo: " + activity.text()) + .withRecipient(activity.from()).withFrom(activity.recipient())); + } + }).join(); + } catch (CompletionException ex) { + if (ex.getCause() instanceof AuthenticationException) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + else { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } } catch (Exception ex) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } From f44884f5c49c6b3a66c18b0d7a22c30cdfe6823b Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 09:29:21 -0500 Subject: [PATCH 05/26] Removed unused import to make PMD happy. --- .../bot/connector/authentication/ChannelValidation.java | 1 - .../bot/connector/authentication/EmulatorValidation.java | 1 - .../connector/authentication/EnterpriseChannelValidation.java | 1 - .../bot/connector/authentication/JwtTokenValidation.java | 1 - 4 files changed, 4 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index 4c39a9977..e5ae4adac 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -7,7 +7,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; public class ChannelValidation { /** diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index 561070c0f..ce951ccf4 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -9,7 +9,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; /** * Validates and Examines JWT tokens from the Bot Framework Emulator diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index a085045aa..2cb597bb8 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -9,7 +9,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; public class EnterpriseChannelValidation { private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 90fa8c672..5fb679a8e 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -51,7 +51,6 @@ public static CompletableFuture authenticateRequest(Activity act } // No Auth Header. Auth is required. Request is not authorized. - CompletableFuture result = CompletableFuture.completedFuture(null); throw new AuthenticationException("No Auth Header. Auth is required."); } From 71ff30c4ddf2a530860058abf8234710f8fd091d Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 09:43:16 -0500 Subject: [PATCH 06/26] Removed use of java.util.Logging --- .../bot/connector/authentication/OpenIdMetadata.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java index 69624c073..150bd891f 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java @@ -16,11 +16,11 @@ import java.security.interfaces.RSAPublicKey; import java.util.HashMap; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class OpenIdMetadata { - private static final Logger LOGGER = Logger.getLogger( OpenIdMetadata.class.getName() ); + private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdMetadata.class); private String url; private long lastUpdated; @@ -52,7 +52,7 @@ private String refreshCache() { return IOUtils.toString(keysUrl); } catch (IOException e) { String errorDescription = String.format("Failed to load openID config: %s", e.getMessage()); - LOGGER.log(Level.WARNING, errorDescription); + LOGGER.warn(errorDescription); } return null; } @@ -67,7 +67,7 @@ private OpenIdMetadataKey findKey(String keyId) { return key; } catch (JwkException e) { String errorDescription = String.format("Failed to load keys: %s", e.getMessage()); - LOGGER.log(Level.WARNING, errorDescription); + LOGGER.warn(errorDescription); } return null; } From c939b93326936ed3488624789480774ab89dd56a Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 13:32:48 -0500 Subject: [PATCH 07/26] Added JwtTokenvalidation.ChannelNoHeaderAuthenticationEnabledShouldThrow test. --- .../bot/connector/JwtTokenValidationTests.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index 749fc8a40..a9d0cc624 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -202,6 +202,24 @@ public void ChannelAuthenticationDisabledShouldBeAnonymous() throws ExecutionExc Assert.assertEquals("anonymous", identity.getIssuer()); } + @Test + public void ChannelNoHeaderAuthenticationEnabledShouldThrow() throws IOException, ExecutionException, InterruptedException { + try { + String header = ""; + CredentialProvider credentials = new SimpleCredentialProvider(APPID, APPPASSWORD); + JwtTokenValidation.authenticateRequest( + new Activity().withServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"), + header, + credentials, + new SimpleChannelProvider()).join(); + Assert.fail("Should have thrown AuthenticationException"); + } catch(CompletionException e) { + Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } + + Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/")); + } + /** * Tests with no authentication header and makes sure the service URL is not added to the trusted list. */ From 2491f71a91603819b197bbd39b9d6c327be44a4d Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 15:50:32 -0500 Subject: [PATCH 08/26] Added MicrosoftAppCredentialsTests, SimpleChannelProviderTest, and SimpleCredentialProviderTests. --- .../MicrosoftAppCredentials.java | 27 ++++++-- .../SimpleCredentialProvider.java | 19 ++++++ .../MicrosoftAppCredentialsTests.java | 64 +++++++++++++++++++ .../connector/SimpleChannelProviderTests.java | 36 +++++++++++ .../SimpleCredentialProviderTests.java | 32 ++++++++++ 5 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java create mode 100644 libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleChannelProviderTests.java create mode 100644 libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleCredentialProviderTests.java diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index a62a2723d..a6d7bad70 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -119,7 +119,13 @@ public String channelAuthTenant() { } public void setChannelAuthTenant(String authTenant) throws MalformedURLException { - channelAuthTenant = new URL(authTenant).toString(); + String originalAuthTenant = channelAuthTenant; + try { + channelAuthTenant = authTenant; + new URL(oAuthEndpoint()).toString(); + } catch(MalformedURLException e) { + channelAuthTenant = originalAuthTenant; + } } public MicrosoftAppCredentials withChannelAuthTenant(String authTenant) throws MalformedURLException { @@ -135,7 +141,7 @@ public String oAuthScope() { return AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE; } - public Future getToken() throws MalformedURLException { + public Future getToken() { return getAuthenticator().acquireToken(); } @@ -143,12 +149,19 @@ protected boolean ShouldSetToken(String url) { return isTrustedServiceUrl(url); } - private AdalAuthenticator getAuthenticator() throws MalformedURLException { - if (this.authenticator == null) { - this.authenticator = new AdalAuthenticator( - new ClientCredential(this.appId, this.appPassword), - new OAuthConfiguration(oAuthEndpoint(), oAuthScope())); + private AdalAuthenticator getAuthenticator() { + try { + if (this.authenticator == null) { + this.authenticator = new AdalAuthenticator( + new ClientCredential(this.appId, this.appPassword), + new OAuthConfiguration(oAuthEndpoint(), oAuthScope())); + } + } catch(MalformedURLException e) { + // intentional no-op. This class validates the URL on construction or setChannelAuthTenant. + // That is... this will never happen. + LoggerFactory.getLogger(MicrosoftAppCredentials.class).error("getAuthenticator", e); } + return this.authenticator; } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java index ce5789611..80ffd2853 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/SimpleCredentialProvider.java @@ -47,16 +47,35 @@ public void setPassword(String password) { this.password = password; } + /** + * Validates an app ID. + * + * @param appId The app ID to validate. + * @return If the task is successful, the result is true if appId is valid for the controller; otherwise, false. + */ @Override public CompletableFuture isValidAppIdAsync(String appId) { return CompletableFuture.completedFuture(StringUtils.equals(appId, this.appId)); } + /** + * Gets the app password for a given bot app ID. + * + * @param appId The ID of the app to get the password for. + * @return If the task is successful and the app ID is valid, the result + * contains the password; otherwise, null. + */ @Override public CompletableFuture getAppPasswordAsync(String appId) { return CompletableFuture.completedFuture(StringUtils.equals(appId, this.appId) ? this.password : null); } + /** + * Checks whether bot authentication is disabled. + * + * @return A task that represents the work queued to execute If the task is successful and bot authentication + * is disabled, the result is true; otherwise, false. + */ @Override public CompletableFuture isAuthenticationDisabledAsync() { return CompletableFuture.completedFuture(StringUtils.isEmpty(this.appId)); diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java new file mode 100644 index 000000000..831b964ac --- /dev/null +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.net.MalformedURLException; +import java.net.URL; +import java.time.LocalDateTime; +import java.util.concurrent.ExecutionException; + +public class MicrosoftAppCredentialsTests { + @Test + public void ValidUrlTrusted() { + MicrosoftAppCredentials.trustServiceUrl("https://goodurl.com"); + Assert.assertTrue(MicrosoftAppCredentials.isTrustedServiceUrl("https://goodurl.com")); + } + + @Test + public void InvalidUrlTrusted() { + MicrosoftAppCredentials.trustServiceUrl("badurl"); + Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("badurl")); + } + + @Test + public void TrustedUrlExpiration() throws InterruptedException { + // There is a +5 minute window for an expired url + MicrosoftAppCredentials.trustServiceUrl("https://goodurl.com", LocalDateTime.now().minusMinutes(6)); + Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://goodurl.com")); + + MicrosoftAppCredentials.trustServiceUrl("https://goodurl.com", LocalDateTime.now().minusMinutes(4)); + Assert.assertTrue(MicrosoftAppCredentials.isTrustedServiceUrl("https://goodurl.com")); + } + + @Test + public void ValidateAuthEndpoint() { + try { + // In Java, about the only thing that can cause a MalformedURLException in a missing or unknown protocol. + // At any rate, this should validate someone didn't mess up the oAuth Endpoint for the class. + MicrosoftAppCredentials credentials = new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F"); + new URL(credentials.oAuthEndpoint()); + + credentials.setChannelAuthTenant("tenant.com"); + + MicrosoftAppCredentials credentialsWithTenant = + new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F", "tenant.com"); + + } catch(MalformedURLException e) { + Assert.fail("Should not have thrown MalformedURLException"); + } + } + + @Test + public void GetToken() throws InterruptedException, ExecutionException { + MicrosoftAppCredentials credentials = new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F"); + AuthenticationResult token = credentials.getToken().get(); + Assert.assertFalse(StringUtils.isEmpty(token.getAccessToken())); + } +} diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleChannelProviderTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleChannelProviderTests.java new file mode 100644 index 000000000..6ae6f4e72 --- /dev/null +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleChannelProviderTests.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +import com.microsoft.bot.connector.authentication.GovernmentAuthenticationConstants; +import com.microsoft.bot.connector.authentication.SimpleChannelProvider; +import org.junit.Assert; +import org.junit.Test; + +public class SimpleChannelProviderTests { + @Test + public void PublicChannelProvider() { + SimpleChannelProvider channel = new SimpleChannelProvider(); + Assert.assertTrue(channel.isPublicAzure()); + Assert.assertFalse(channel.isGovernment()); + } + + @Test + public void GovernmentChannelProvider() { + SimpleChannelProvider channel = new SimpleChannelProvider(GovernmentAuthenticationConstants.CHANNELSERVICE); + Assert.assertFalse(channel.isPublicAzure()); + Assert.assertTrue(channel.isGovernment()); + } + + @Test + public void GetChannelService() { + try { + SimpleChannelProvider channel = new SimpleChannelProvider(GovernmentAuthenticationConstants.CHANNELSERVICE); + String service = channel.getChannelService().join(); + Assert.assertEquals(service, GovernmentAuthenticationConstants.CHANNELSERVICE); + } catch (Throwable t) { + Assert.fail("Should not have thrown " + t.getClass().getName()); + } + } +} diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleCredentialProviderTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleCredentialProviderTests.java new file mode 100644 index 000000000..9c1f6f559 --- /dev/null +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/SimpleCredentialProviderTests.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +import com.microsoft.bot.connector.authentication.SimpleCredentialProvider; +import org.junit.Assert; +import org.junit.Test; + +public class SimpleCredentialProviderTests { + @Test + public void ValidAppIdAsync() { + SimpleCredentialProvider credentialProvider = new SimpleCredentialProvider("appid", "pwd"); + + Assert.assertTrue(credentialProvider.isValidAppIdAsync("appid").join()); + Assert.assertFalse(credentialProvider.isValidAppIdAsync("wrongappid").join()); + } + + @Test + public void AppPasswordAsync() { + SimpleCredentialProvider credentialProvider = new SimpleCredentialProvider("appid", "pwd"); + + Assert.assertEquals(credentialProvider.getAppPasswordAsync("appid").join(), "pwd"); + Assert.assertNull(credentialProvider.getAppPasswordAsync("wrongappid").join()); + } + + @Test + public void AuthenticationDisabledAsync() { + Assert.assertFalse(new SimpleCredentialProvider("appid", "pwd").isAuthenticationDisabledAsync().join()); + Assert.assertTrue(new SimpleCredentialProvider(null, null).isAuthenticationDisabledAsync().join()); + } +} From 3f90a2b031b76fc9eda9b6bba19ead74d37bf282 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 21 Aug 2019 17:09:10 -0500 Subject: [PATCH 09/26] Added EmulatorValidationTests --- .../authentication/EmulatorValidation.java | 28 ++++++++++------- .../connector/EmulatorValidationTests.java | 31 +++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EmulatorValidationTests.java diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index ce951ccf4..ec5044b93 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -48,17 +48,21 @@ public static Boolean isTokenFromEmulator(String authHeader) { } // Parse the Big Long String into an actual token. - DecodedJWT decodedJWT = JWT.decode(token); - - // Is there an Issuer? - if (decodedJWT.getIssuer().isEmpty()) { - // No Issuer, means it's not from the Emulator. + try { + DecodedJWT decodedJWT = JWT.decode(token); + + // Is there an Issuer? + if (StringUtils.isEmpty(decodedJWT.getIssuer())) { + // No Issuer, means it's not from the Emulator. + return false; + } + + // Is the token issues by a source we consider to be the emulator? + // Not a Valid Issuer. This is NOT a Bot Framework Emulator Token. + return TOKENVALIDATIONPARAMETERS.validIssuers.contains(decodedJWT.getIssuer()); + } catch (Throwable t) { return false; } - - // Is the token issues by a source we consider to be the emulator? - // Not a Valid Issuer. This is NOT a Bot Framework Emulator Token. - return TOKENVALIDATIONPARAMETERS.validIssuers.contains(decodedJWT.getIssuer()); } /** @@ -70,7 +74,7 @@ public static Boolean isTokenFromEmulator(String authHeader) { * @param channelProvider The channelService value that distinguishes public Azure from US Government Azure. * @param channelId The ID of the channel to validate. * @return A valid ClaimsIdentity. - * + *

* On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ @@ -88,11 +92,11 @@ public static CompletableFuture authenticateToken(String authHea * @param channelId The ID of the channel to validate. * @param authConfig The authentication configuration. * @return A valid ClaimsIdentity. - * + *

* On join: * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) { String openIdMetadataUrl = channelProvider != null && channelProvider.isGovernment() ? GovernmentAuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL : AuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EmulatorValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EmulatorValidationTests.java new file mode 100644 index 000000000..24e27839e --- /dev/null +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/EmulatorValidationTests.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.connector; + +import com.microsoft.bot.connector.authentication.EmulatorValidation; +import org.junit.Assert; +import org.junit.Test; + +public class EmulatorValidationTests { + @Test + public void NoSchemeTokenIsNotFromEmulator() { + Assert.assertFalse(EmulatorValidation.isTokenFromEmulator("AbCdEf123456")); + } + + @Test + public void OnePartTokenIsNotFromEmulator() { + Assert.assertFalse(EmulatorValidation.isTokenFromEmulator("Bearer AbCdEf123456")); + } + + @Test + public void NoIssuerIsNotFromEmulator() { + Assert.assertFalse(EmulatorValidation.isTokenFromEmulator("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJtZXNzYWdlIjoiSldUIFJ1bGVzISIsImlhdCI6MTQ1OTQ0ODExOSwiZXhwIjoxNDU5NDU0NTE5fQ.-yIVBD5b73C75osbmwwshQNRC7frWUYrqaTjTpza2y4")); + } + + @Test + public void ValidTokenSuccess() { + String emToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImllX3FXQ1hoWHh0MXpJRXN1NGM3YWNRVkduNCIsImtpZCI6ImllX3FXQ1hoWHh0MXpJRXN1NGM3YWNRVkduNCJ9.eyJhdWQiOiI5YzI4NmUyZi1lMDcwLTRhZjUtYTNmMS0zNTBkNjY2MjE0ZWQiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kNmQ0OTQyMC1mMzliLTRkZjctYTFkYy1kNTlhOTM1ODcxZGIvIiwiaWF0IjoxNTY2NDIyMTY3LCJuYmYiOjE1NjY0MjIxNjcsImV4cCI6MTU2NjQyNjA2NywiYWlvIjoiNDJGZ1lKaDBoK0VmRDAvNnVWaUx6NHZuL25UK0RnQT0iLCJhcHBpZCI6IjljMjg2ZTJmLWUwNzAtNGFmNS1hM2YxLTM1MGQ2NjYyMTRlZCIsImFwcGlkYWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2Q2ZDQ5NDIwLWYzOWItNGRmNy1hMWRjLWQ1OWE5MzU4NzFkYi8iLCJ0aWQiOiJkNmQ0OTQyMC1mMzliLTRkZjctYTFkYy1kNTlhOTM1ODcxZGIiLCJ1dGkiOiJPUXNSLWExUlpFS2tJcG9seUNJUUFBIiwidmVyIjoiMS4wIn0.J9qHO11oZlrpDU3MJcTJe3ErUqj0kw-ZQioYKbkwZ7ZpAx5hl01BETts-LOaE14tImqYqM2K86ZyX5LuAp2snru9LJ4S6-cVZ1_lp_IY4r61UuUJRiVUzn25kRZEN-TFi8Aj1iyL-ueeNr52MM1Sr2UUH73fwrferH8_0qa1IYc7affhjlFEWxSte0SN7iT5WaYK32d_nsgzJdZiCMZJPCpG39U2FYnSI8q7vvYjNbp8wDJc46Q4Jdd3zXYRgHWRBGL_EEkzzk9IFpHN7WoVaqNtgMiA4Vf8bde3eAS5lBBtE5VZ0F6fG4Qeg6zjOAxPBZqvAASMpgyDlSQMknevOQ"; + Assert.assertTrue(EmulatorValidation.isTokenFromEmulator(emToken)); + } +} From ace471cb7f6d33d010f621ae59793c47b34c46d5 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 08:07:14 -0500 Subject: [PATCH 10/26] Using MicrosoftGovernmentAppCredentials for Jwt Gov tests. --- .../bot/connector/BotConnectorTestBase.java | 2 +- .../bot/connector/JwtTokenValidationTests.java | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java index 9f1ff581b..e649af8da 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java @@ -6,7 +6,7 @@ import com.microsoft.rest.RestClient; public class BotConnectorTestBase extends TestBase { - protected RestConnectorClient connector; + protected ConnectorClient connector; protected ChannelAccount bot; protected ChannelAccount user; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index a9d0cc624..b50d0007c 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -22,10 +22,14 @@ public class JwtTokenValidationTests { private static final String APPID = "2cd87869-38a0-4182-9251-d056e8f0ac24"; private static final String APPPASSWORD = "2.30Vs3VQLKt974F"; - private static String getHeaderToken() throws MalformedURLException, ExecutionException, InterruptedException { + private static String getHeaderToken() throws ExecutionException, InterruptedException { return String.format("Bearer %s", new MicrosoftAppCredentials(APPID, APPPASSWORD).getToken().get().getAccessToken()); } + private static String getGovHeaderToken() throws ExecutionException, InterruptedException { + return String.format("Bearer %s", new MicrosoftGovernmentAppCredentials(APPID, APPPASSWORD).getToken().get().getAccessToken()); + } + @Test public void ConnectorAuthHeaderCorrectAppIdAndServiceUrlShouldValidate() throws IOException, ExecutionException, InterruptedException { String header = getHeaderToken(); @@ -389,13 +393,14 @@ public void GovernmentChannelValidation_WrongAudienceClaimIssuer_Fails() { */ private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String appId, String pwd, String channelService) throws IOException, ExecutionException, InterruptedException { - String header = getHeaderToken(); - JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(header, appId, pwd, channelService); + ChannelProvider channel = new SimpleChannelProvider(channelService); + String header = channel.isGovernment()?getGovHeaderToken():getHeaderToken(); + + JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(header, appId, pwd, channel); } - private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String header, String appId, String pwd, String channelService) { + private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String header, String appId, String pwd, ChannelProvider channel) { CredentialProvider credentials = new SimpleCredentialProvider(appId, pwd); - ChannelProvider channel = new SimpleChannelProvider(channelService); try { ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader( From f3d41517cd6791b8d06121cad29d7f17833d6b56 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 09:03:29 -0500 Subject: [PATCH 11/26] Moved EmulatorValidation TokenValidationParameters. --- .../authentication/EmulatorValidation.java | 18 +++++++++++++++++- .../TokenValidationParameters.java | 18 ------------------ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index ec5044b93..673ee9c44 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -8,6 +8,8 @@ import com.microsoft.aad.adal4j.AuthenticationException; import org.apache.commons.lang3.StringUtils; +import java.time.Duration; +import java.util.ArrayList; import java.util.concurrent.CompletableFuture; /** @@ -17,7 +19,21 @@ public class EmulatorValidation { /** * TO BOT FROM EMULATOR: Token validation parameters when connecting to a channel. */ - private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = TokenValidationParameters.toBotFromEmulatorTokenValidationParameters(); + private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ + this.validateIssuer = true; + this.validIssuers = new ArrayList() {{ + add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); // Auth v3.1, 1.0 token + add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); // Auth v3.1, 2.0 token + add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); // Auth v3.2, 1.0 token + add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); // Auth v3.2, 2.0 token + add("https://sts.windows.net/cab8a31a-1906-4287-a0d8-4eef66b95f6e/"); // Auth for US Gov, 1.0 token + add("https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0"); // Auth for US Gov, 2.0 token + }}; + this.validateAudience = false; + this.validateLifetime = true; + this.clockSkew = Duration.ofMinutes(5); + this.requireSignedTokens = true; + }}; /** * Determines if a given Auth header is from the Bot Framework Emulator diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java index 75affa36d..530eb4c76 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java @@ -31,24 +31,6 @@ public TokenValidationParameters(boolean validateIssuer, List validIssue this.requireSignedTokens = requireSignedTokens; } - static TokenValidationParameters toBotFromEmulatorTokenValidationParameters() { - return new TokenValidationParameters() {{ - this.validateIssuer = true; - this.validIssuers = new ArrayList() {{ - add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); // Auth v3.1, 1.0 token - add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); // Auth v3.1, 2.0 token - add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); // Auth v3.2, 1.0 token - add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); // Auth v3.2, 2.0 token - add("https://sts.windows.net/cab8a31a-1906-4287-a0d8-4eef66b95f6e/"); // Auth for US Gov, 1.0 token - add("https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0"); // Auth for US Gov, 2.0 token - }}; - this.validateAudience = false; - this.validateLifetime = true; - this.clockSkew = Duration.ofMinutes(5); - this.requireSignedTokens = true; - }}; - } - static TokenValidationParameters toBotFromChannelTokenValidationParameters() { return new TokenValidationParameters() {{ this.validateIssuer = true; From ff2a241351332ff2c987802701cd7123e5217c2d Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 09:29:36 -0500 Subject: [PATCH 12/26] Using ExecutorFactory for all CompletableFuture async calls. --- .../bot/builder/BotFrameworkAdapter.java | 7 +- .../bot/builder/MemoryTranscriptStore.java | 610 ++++----- .../bot/builder/TurnContextImpl.java | 1217 ++++++++--------- .../CatchException_MiddlewareTest.java | 219 +-- .../bot/builder/DictionaryStorage.java | 259 ++-- .../bot/builder/adapters/TestFlow.java | 937 ++++++------- .../EnterpriseChannelValidation.java | 3 +- .../authentication/JwtTokenExtractor.java | 3 +- .../authentication/JwtTokenValidation.java | 3 +- .../connector/authentication/OAuthClient.java | 9 +- .../bot/connector/OAuthTestBase.java | 2 +- .../bot/sample/servlet/EchoServlet.java | 3 +- .../bot/sample/spring/BotController.java | 3 +- 13 files changed, 1631 insertions(+), 1644 deletions(-) diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index 11f41aa9c..bbb50bc4e 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -5,6 +5,7 @@ import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.Conversations; +import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.connector.rest.RestConversations; @@ -628,7 +629,7 @@ public CompletableFuture CreateConversation(String channelId, String serviceUrl, // Should never happen throw new RuntimeException(String.format("Conversations create issue - returned %d conversations", results.size())); } - }); + }, ExecutorFactory.getExecutor()); } @@ -719,7 +720,7 @@ private CompletableFuture CreateConnectorClientAsync(String ser throw new RuntimeException(String.format("Bad Service URL: %s", serviceUrl)); } } - }); + }, ExecutorFactory.getExecutor()); } @@ -772,7 +773,7 @@ private CompletableFuture GetAppCredentialsAsync(String this.appCredentialMap.put(appId, appCredentials); return appCredentials; - }); + }, ExecutorFactory.getExecutor()); return result; } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java index cf36ef092..6ddbde3da 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java @@ -1,310 +1,300 @@ -package com.microsoft.bot.builder; - - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -import com.microsoft.bot.schema.models.Activity; -import org.joda.time.DateTime; - -import java.time.Instant; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinWorkerThread; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * The memory transcript store stores transcripts in volatile memory in a Dictionary. - *

- *

- * Because this uses an unbounded volitile dictionary this should only be used for unit tests or non-production environments. - */ -public class MemoryTranscriptStore implements TranscriptStore { - private HashMap>> channels = new HashMap>>(); - final ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() { - @Override - public ForkJoinWorkerThread newThread(ForkJoinPool pool) { - final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName("TestFlow-" + worker.getPoolIndex()); - return worker; - } - }; - - final ExecutorService executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), factory, null, false); - - - /** - * Logs an activity to the transcript. - * - * @param activity The activity to log. - * @return A CompletableFuture that represents the work queued to execute. - */ - public final void LogActivityAsync(Activity activity) { - if (activity == null) { - throw new NullPointerException("activity cannot be null for LogActivity()"); - } - - synchronized (this.channels) { - HashMap> channel; - if (!this.channels.containsKey(activity.channelId())) { - channel = new HashMap>(); - this.channels.put(activity.channelId(), channel); - } else { - channel = this.channels.get(activity.channelId()); - } - - ArrayList transcript = null; - - - if (!channel.containsKey(activity.conversation().id())) { - transcript = new ArrayList(); - channel.put(activity.conversation().id(), transcript); - } else { - transcript = channel.get(activity.conversation().id()); - } - - transcript.add(activity); - } - - } - - /** - * Gets from the store activities that match a set of criteria. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation. - * @param continuationToken - * @return A task that represents the work queued to execute. - * If the task completes successfully, the result contains the matching activities. - */ - - public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken) { - return GetTranscriptActivitiesAsync(channelId, conversationId, continuationToken, null); - } - - /** - * Gets from the store activities that match a set of criteria. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation. - * @return A task that represents the work queued to execute. - * If the task completes successfully, the result contains the matching activities. - */ - - public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId) { - return GetTranscriptActivitiesAsync(channelId, conversationId, null, null); - } - - /** - * Gets from the store activities that match a set of criteria. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation. - * @param continuationToken - * @param startDate A cutoff date. Activities older than this date are not included. - * @return A task that represents the work queued to execute. - * If the task completes successfully, the result contains the matching activities. - */ - public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken, DateTime startDate) { - return CompletableFuture.supplyAsync(() -> { - if (channelId == null) { - throw new NullPointerException(String.format("missing %1$s", "channelId")); - } - - if (conversationId == null) { - throw new NullPointerException(String.format("missing %1$s", "conversationId")); - } - - PagedResult pagedResult = new PagedResult(); - synchronized (channels) { - HashMap> channel; - if (!channels.containsKey(channelId)) { - return pagedResult; - } - channel = channels.get(channelId); - ArrayList transcript; - - if (!channel.containsKey(conversationId)) { - return pagedResult; - } - transcript = channel.get(conversationId); - if (continuationToken != null) { - List items = transcript.stream() - .sorted(Comparator.comparing(Activity::timestamp)) - .filter(a -> a.timestamp().compareTo(startDate) >= 0) - .filter(skipwhile(a -> !a.id().equals(continuationToken))) - .skip(1) - .limit(20) - .collect(Collectors.toList()); - - pagedResult.items(items.toArray(new Activity[items.size()])); - - if (pagedResult.getItems().length == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).id()); - } - } else { - List items = transcript.stream() - .sorted(Comparator.comparing(Activity::timestamp)) - .filter(a -> a.timestamp().compareTo((startDate == null) ? new DateTime(Long.MIN_VALUE) : startDate) >= 0) - .limit(20) - .collect(Collectors.toList()); - pagedResult.items(items.toArray(new Activity[items.size()])); - if (items.size() == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).id()); - } - } - } - - return pagedResult; - - }, this.executor); - } - - /** - * Deletes conversation data from the store. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation to delete. - * @return A task that represents the work queued to execute. - */ - public final CompletableFuture DeleteTranscriptAsync(String channelId, String conversationId) { - return CompletableFuture.runAsync(() -> { - if (channelId == null) { - throw new NullPointerException(String.format("%1$s should not be null", "channelId")); - } - - if (conversationId == null) { - throw new NullPointerException(String.format("%1$s should not be null", "conversationId")); - } - - synchronized (this.channels) { - if (!this.channels.containsKey(channelId)) { - return; - } - HashMap> channel = this.channels.get(channelId); - if (channel.containsKey(conversationId)) { - channel.remove(conversationId); - } - } - }, this.executor); - } - - /** - * Gets the conversations on a channel from the store. - * - * @param channelId The ID of the channel. - * @return A task that represents the work queued to execute. - */ - - public final CompletableFuture> ListTranscriptsAsync(String channelId) { - return ListTranscriptsAsync(channelId, null); - } - - /** - * Gets the conversations on a channel from the store. - * - * @param channelId The ID of the channel. - * @param continuationToken - * @return A task that represents the work queued to execute. - */ - - public final CompletableFuture> ListTranscriptsAsync(String channelId, String continuationToken) { - return CompletableFuture.supplyAsync(() -> { - if (channelId == null) { - throw new NullPointerException(String.format("missing %1$s", "channelId")); - } - - PagedResult pagedResult = new PagedResult(); - synchronized (channels) { - - if (!channels.containsKey(channelId)) { - return pagedResult; - } - - HashMap> channel = channels.get(channelId); - if (continuationToken != null) { - List items = channel.entrySet().stream() - .map(c -> { - OffsetDateTime offsetDateTime = null; - if (c.getValue().stream().findFirst().isPresent()) { - DateTime dt = c.getValue().stream().findFirst().get().timestamp(); - // convert to DateTime to OffsetDateTime - Instant instant = Instant.ofEpochMilli(dt.getMillis()); - ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); - offsetDateTime = instant.atOffset(offset); - } else { - offsetDateTime = OffsetDateTime.now(); - } - return new Transcript() - .withChannelId(channelId) - .withId(c.getKey()) - .withCreated(offsetDateTime); - } - ) - .sorted(Comparator.comparing(Transcript::getCreated)) - .filter(skipwhile(c -> !c.getId().equals(continuationToken))) - .skip(1) - .limit(20) - .collect(Collectors.toList()); - pagedResult.items(items.toArray(new Transcript[items.size()])); - if (items.size() == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); - } - } else { - - List items = channel.entrySet().stream() - .map(c -> { - OffsetDateTime offsetDateTime = null; - if (c.getValue().stream().findFirst().isPresent()) { - DateTime dt = c.getValue().stream().findFirst().get().timestamp(); - // convert to DateTime to OffsetDateTime - Instant instant = Instant.ofEpochMilli(dt.getMillis()); - ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); - offsetDateTime = instant.atOffset(offset); - } else { - offsetDateTime = OffsetDateTime.now(); - } - return new Transcript() - .withChannelId(channelId) - .withId(c.getKey()) - .withCreated(offsetDateTime); - } - ) - .sorted(Comparator.comparing(Transcript::getCreated)) - .limit(20) - .collect(Collectors.toList()); - pagedResult.items(items.toArray(new Transcript[items.size()])); - if (items.size() == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); - } - } - } - return pagedResult; - }, this.executor); - } - - /** - * Emulate C# SkipWhile. - * Stateful - * - * @param func1 predicate to apply - * @param type - * @return if the predicate condition is true - */ - public static Predicate skipwhile(Function func1) { - final boolean[] started = {false}; - return t -> started[0] || (started[0] = (boolean) func1.apply(t)); - } - -} \ No newline at end of file +package com.microsoft.bot.builder; + + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +import com.microsoft.bot.connector.ExecutorFactory; +import com.microsoft.bot.schema.models.Activity; +import org.joda.time.DateTime; + +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * The memory transcript store stores transcripts in volatile memory in a Dictionary. + *

+ *

+ * Because this uses an unbounded volitile dictionary this should only be used for unit tests or non-production environments. + */ +public class MemoryTranscriptStore implements TranscriptStore { + private HashMap>> channels = new HashMap>>(); + + /** + * Logs an activity to the transcript. + * + * @param activity The activity to log. + * @return A CompletableFuture that represents the work queued to execute. + */ + public final void LogActivityAsync(Activity activity) { + if (activity == null) { + throw new NullPointerException("activity cannot be null for LogActivity()"); + } + + synchronized (this.channels) { + HashMap> channel; + if (!this.channels.containsKey(activity.channelId())) { + channel = new HashMap>(); + this.channels.put(activity.channelId(), channel); + } else { + channel = this.channels.get(activity.channelId()); + } + + ArrayList transcript = null; + + + if (!channel.containsKey(activity.conversation().id())) { + transcript = new ArrayList(); + channel.put(activity.conversation().id(), transcript); + } else { + transcript = channel.get(activity.conversation().id()); + } + + transcript.add(activity); + } + + } + + /** + * Gets from the store activities that match a set of criteria. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation. + * @param continuationToken + * @return A task that represents the work queued to execute. + * If the task completes successfully, the result contains the matching activities. + */ + + public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken) { + return GetTranscriptActivitiesAsync(channelId, conversationId, continuationToken, null); + } + + /** + * Gets from the store activities that match a set of criteria. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation. + * @return A task that represents the work queued to execute. + * If the task completes successfully, the result contains the matching activities. + */ + + public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId) { + return GetTranscriptActivitiesAsync(channelId, conversationId, null, null); + } + + /** + * Gets from the store activities that match a set of criteria. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation. + * @param continuationToken + * @param startDate A cutoff date. Activities older than this date are not included. + * @return A task that represents the work queued to execute. + * If the task completes successfully, the result contains the matching activities. + */ + public final CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken, DateTime startDate) { + return CompletableFuture.supplyAsync(() -> { + if (channelId == null) { + throw new NullPointerException(String.format("missing %1$s", "channelId")); + } + + if (conversationId == null) { + throw new NullPointerException(String.format("missing %1$s", "conversationId")); + } + + PagedResult pagedResult = new PagedResult(); + synchronized (channels) { + HashMap> channel; + if (!channels.containsKey(channelId)) { + return pagedResult; + } + channel = channels.get(channelId); + ArrayList transcript; + + if (!channel.containsKey(conversationId)) { + return pagedResult; + } + transcript = channel.get(conversationId); + if (continuationToken != null) { + List items = transcript.stream() + .sorted(Comparator.comparing(Activity::timestamp)) + .filter(a -> a.timestamp().compareTo(startDate) >= 0) + .filter(skipwhile(a -> !a.id().equals(continuationToken))) + .skip(1) + .limit(20) + .collect(Collectors.toList()); + + pagedResult.items(items.toArray(new Activity[items.size()])); + + if (pagedResult.getItems().length == 20) { + pagedResult.withContinuationToken(items.get(items.size() - 1).id()); + } + } else { + List items = transcript.stream() + .sorted(Comparator.comparing(Activity::timestamp)) + .filter(a -> a.timestamp().compareTo((startDate == null) ? new DateTime(Long.MIN_VALUE) : startDate) >= 0) + .limit(20) + .collect(Collectors.toList()); + pagedResult.items(items.toArray(new Activity[items.size()])); + if (items.size() == 20) { + pagedResult.withContinuationToken(items.get(items.size() - 1).id()); + } + } + } + + return pagedResult; + + }, ExecutorFactory.getExecutor()); + } + + /** + * Deletes conversation data from the store. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation to delete. + * @return A task that represents the work queued to execute. + */ + public final CompletableFuture DeleteTranscriptAsync(String channelId, String conversationId) { + return CompletableFuture.runAsync(() -> { + if (channelId == null) { + throw new NullPointerException(String.format("%1$s should not be null", "channelId")); + } + + if (conversationId == null) { + throw new NullPointerException(String.format("%1$s should not be null", "conversationId")); + } + + synchronized (this.channels) { + if (!this.channels.containsKey(channelId)) { + return; + } + HashMap> channel = this.channels.get(channelId); + if (channel.containsKey(conversationId)) { + channel.remove(conversationId); + } + } + }, ExecutorFactory.getExecutor()); + } + + /** + * Gets the conversations on a channel from the store. + * + * @param channelId The ID of the channel. + * @return A task that represents the work queued to execute. + */ + + public final CompletableFuture> ListTranscriptsAsync(String channelId) { + return ListTranscriptsAsync(channelId, null); + } + + /** + * Gets the conversations on a channel from the store. + * + * @param channelId The ID of the channel. + * @param continuationToken + * @return A task that represents the work queued to execute. + */ + + public final CompletableFuture> ListTranscriptsAsync(String channelId, String continuationToken) { + return CompletableFuture.supplyAsync(() -> { + if (channelId == null) { + throw new NullPointerException(String.format("missing %1$s", "channelId")); + } + + PagedResult pagedResult = new PagedResult(); + synchronized (channels) { + + if (!channels.containsKey(channelId)) { + return pagedResult; + } + + HashMap> channel = channels.get(channelId); + if (continuationToken != null) { + List items = channel.entrySet().stream() + .map(c -> { + OffsetDateTime offsetDateTime = null; + if (c.getValue().stream().findFirst().isPresent()) { + DateTime dt = c.getValue().stream().findFirst().get().timestamp(); + // convert to DateTime to OffsetDateTime + Instant instant = Instant.ofEpochMilli(dt.getMillis()); + ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); + offsetDateTime = instant.atOffset(offset); + } else { + offsetDateTime = OffsetDateTime.now(); + } + return new Transcript() + .withChannelId(channelId) + .withId(c.getKey()) + .withCreated(offsetDateTime); + } + ) + .sorted(Comparator.comparing(Transcript::getCreated)) + .filter(skipwhile(c -> !c.getId().equals(continuationToken))) + .skip(1) + .limit(20) + .collect(Collectors.toList()); + pagedResult.items(items.toArray(new Transcript[items.size()])); + if (items.size() == 20) { + pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); + } + } else { + + List items = channel.entrySet().stream() + .map(c -> { + OffsetDateTime offsetDateTime = null; + if (c.getValue().stream().findFirst().isPresent()) { + DateTime dt = c.getValue().stream().findFirst().get().timestamp(); + // convert to DateTime to OffsetDateTime + Instant instant = Instant.ofEpochMilli(dt.getMillis()); + ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); + offsetDateTime = instant.atOffset(offset); + } else { + offsetDateTime = OffsetDateTime.now(); + } + return new Transcript() + .withChannelId(channelId) + .withId(c.getKey()) + .withCreated(offsetDateTime); + } + ) + .sorted(Comparator.comparing(Transcript::getCreated)) + .limit(20) + .collect(Collectors.toList()); + pagedResult.items(items.toArray(new Transcript[items.size()])); + if (items.size() == 20) { + pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); + } + } + } + return pagedResult; + }, ExecutorFactory.getExecutor()); + } + + /** + * Emulate C# SkipWhile. + * Stateful + * + * @param func1 predicate to apply + * @param type + * @return if the predicate condition is true + */ + public static Predicate skipwhile(Function func1) { + final boolean[] started = {false}; + return t -> started[0] || (started[0] = (boolean) func1.apply(t)); + } + +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java index c955db952..315248a0e 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java @@ -1,615 +1,602 @@ -package com.microsoft.bot.builder; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.InputHints; -import com.microsoft.bot.schema.models.ResourceResponse; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.*; - -import static com.microsoft.bot.schema.models.ActivityTypes.MESSAGE; -import static com.microsoft.bot.schema.models.ActivityTypes.TRACE; -import static java.util.stream.Collectors.toList; - -/** - * Provides context for a turn of a bot. - * Context provides information needed to process an incoming activity. - * The context object is created by a {@link BotAdapter} and persists for the - * length of the turn. - * {@linkalso Bot} - * {@linkalso Middleware} - */ -public class TurnContextImpl implements TurnContext, AutoCloseable { - private final BotAdapter adapter; - private final ActivityImpl activity; - private Boolean responded = false; - - private final List onSendActivities = new ArrayList(); - private final List onUpdateActivity = new ArrayList(); - private final List onDeleteActivity = new ArrayList(); - - private final TurnContextServiceCollection turnServices; - ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() - { - @Override - public ForkJoinWorkerThread newThread(ForkJoinPool pool) - { - final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName("TestFlow-" + worker.getPoolIndex()); - return worker; - } - }; - - ExecutorService executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), factory, null, true); - - - - /** - * Creates a context object. - * - * @param adapter The adapter creating the context. - * @param activity The incoming activity for the turn; - * or {@code null} for a turn for a proactive message. - * @throws IllegalArgumentException {@code activity} or - * {@code adapter} is {@code null}. - * For use by bot adapter implementations only. - */ - public TurnContextImpl(BotAdapter adapter, ActivityImpl activity) { - if (adapter == null) - throw new IllegalArgumentException("adapter"); - this.adapter = adapter; - if (activity == null) - throw new IllegalArgumentException("activity"); - this.activity = activity; - - turnServices = new TurnContextServiceCollectionImpl(); - } - - - /** - * Adds a response handler for send activity operations. - * - * @param handler The handler to add to the context object. - * @return The updated context object. - * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link SendActivity(Activity)} - * or {@link SendActivities(Activity[])} methods are called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - */ - public TurnContextImpl OnSendActivities(SendActivitiesHandler handler) { - if (handler == null) - throw new IllegalArgumentException("handler"); - - this.onSendActivities.add(handler); - return this; - } - - /** - * Adds a response handler for update activity operations. - * - * @param handler The handler to add to the context object. - * @return The updated context object. - * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link UpdateActivity(Activity)} is called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - */ - public TurnContextImpl OnUpdateActivity(UpdateActivityHandler handler) { - if (handler == null) - throw new IllegalArgumentException("handler"); - - this.onUpdateActivity.add(handler); - return this; - } - - /** - * Adds a response handler for delete activity operations. - * - * @param handler The handler to add to the context object. - * @return The updated context object. - * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link DeleteActivity(string)} is called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - */ - public TurnContextImpl OnDeleteActivity(DeleteActivityHandler handler) { - if (handler == null) - throw new IllegalArgumentException("handler"); - - this.onDeleteActivity.add(handler); - return this; - } - - /** - * Gets the bot adapter that created this context object. - */ - public BotAdapter getAdapter() { - return this.adapter; - } - - /** - * Gets the services registered on this context object. - */ - public TurnContextServiceCollection getServices() { - return this.turnServices; - } - - /** - * Gets the activity associated with this turn; or {@code null} when processing - * a proactive message. - */ - @Override - public Activity getActivity() { - return this.activity; - } - - /** - * Indicates whether at least one response was sent for the current turn. - * - * @return {@code true} if at least one response was sent for the current turn. - * @throws IllegalArgumentException You attempted to set the value to {@code false}. - */ - public boolean getResponded() { - return this.responded; - } - - public void setResponded(boolean responded) { - if (responded == false) { - throw new IllegalArgumentException("TurnContext: cannot set 'responded' to a value of 'false'."); - } - this.responded = true; - } - - /** - * Sends a message activity to the sender of the incoming activity. - * - * @param textReplyToSend The text of the message to send. - * @param speak Optional, text to be spoken by your bot on a speech-enabled - * channel. - * @param inputHint Optional, indicates whether your bot is accepting, - * expecting, or ignoring user input after the message is delivered to the client. - * One of: "acceptingInput", "ignoringInput", or "expectingInput". - * Default is null. - * @return A task that represents the work queued to execute. - * @throws IllegalArgumentException {@code textReplyToSend} is {@code null} or whitespace. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

See the channel's documentation for limits imposed upon the contents of - * {@code textReplyToSend}.

- *

To control various characteristics of your bot's speech such as voice, - * rate, volume, pronunciation, and pitch, specify {@code speak} in - * Speech Synthesis Markup Language (SSML) format.

- */ - @Override - public ResourceResponse SendActivity(String textReplyToSend) throws Exception { - return SendActivity(textReplyToSend, null, null); - } - - @Override - public ResourceResponse SendActivity(String textReplyToSend, String speak) throws Exception { - return SendActivity(textReplyToSend, speak, null); - } - - @Override - public ResourceResponse SendActivity(String textReplyToSend, String speak, String inputHint) throws Exception { - if (StringUtils.isEmpty(textReplyToSend)) - throw new IllegalArgumentException("textReplyToSend"); - - ActivityImpl activityToSend = (ActivityImpl) new ActivityImpl() - .withType(MESSAGE) - .withText(textReplyToSend); - if (speak != null) - activityToSend.withSpeak(speak); - - if (StringUtils.isNotEmpty(inputHint)) - activityToSend.withInputHint(InputHints.fromString(inputHint)); - - return SendActivity(activityToSend); - } - - /** - * Sends an activity to the sender of the incoming activity. - * - * @param activity The activity to send. - * @return A task that represents the work queued to execute. - * @throws IllegalArgumentException {@code activity} is {@code null}. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - */ - @Override - public ResourceResponse SendActivity(Activity activity) throws Exception { - if (activity == null) - throw new IllegalArgumentException("activity"); - - System.out.printf("In SENDEACTIVITYASYNC:"); - System.out.flush(); - Activity[] activities = {activity}; - ResourceResponse[] responses; - try { - responses = SendActivities(activities); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("TurnContext:SendActivity fail %s", e.toString())); - } - if (responses == null || responses.length == 0) { - // It's possible an interceptor prevented the activity from having been sent. - // Just return an empty response in that case. - return null; - } else { - return responses[0]; - } - - } - - /** - * Sends a set of activities to the sender of the incoming activity. - * - * @param activities The activities to send. - * @return A task that represents the work queued to execute. - * If the activities are successfully sent, the task result contains - * an array of {@link ResourceResponse} objects containing the IDs that - * the receiving channel assigned to the activities. - */ - @Override - public ResourceResponse[] SendActivities(Activity[] activities) throws Exception { - // Bind the relevant Conversation Reference properties, such as URLs and - // ChannelId's, to the activities we're about to send. - ConversationReference cr = GetConversationReference(this.activity); - for (Activity a : activities) { - ApplyConversationReference(a, cr); - } - - // Convert the IActivities to Activies. - // Activity[] activityArray = Array.ConvertAll(activities, (input) => (Activity)input); - List activityArray = Arrays.stream(activities).map(input -> (Activity) input).collect(toList()); - - - // Create the list used by the recursive methods. - List activityList = new ArrayList(activityArray); - - Callable ActuallySendStuff = () -> { - // Are the any non-trace activities to send? - // The thinking here is that a Trace event isn't user relevant data - // so the "Responded" flag should not be set by Trace messages being - // sent out. - boolean sentNonTraceActivities = false; - if (!activityList.stream().anyMatch((a) -> a.type() == TRACE)) { - sentNonTraceActivities = true; - } - // Send from the list, which may have been manipulated via the event handlers. - // Note that 'responses' was captured from the root of the call, and will be - // returned to the original caller. - ResourceResponse[] responses = new ResourceResponse[0]; - responses = this.getAdapter().SendActivities(this, activityList.toArray(new ActivityImpl[activityList.size()])); - if (responses != null && responses.length == activityList.size()) { - // stitch up activity ids - for (int i = 0; i < responses.length; i++) { - ResourceResponse response = responses[i]; - Activity activity = activityList.get(i); - activity.withId(response.id()); - } - } - - // If we actually sent something (that's not Trace), set the flag. - if (sentNonTraceActivities) { - this.setResponded(true); - } - return responses; - }; - - List act_list = new ArrayList<>(activityList); - return SendActivitiesInternal(act_list, onSendActivities.iterator(), ActuallySendStuff); - } - - /** - * Replaces an existing activity. - * - * @param activity New replacement activity. - * @return A task that represents the work queued to execute. - * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. - * @throws System.AggregateException One or more exceptions occurred during the operation. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

- */ - @Override - public ResourceResponse UpdateActivity(Activity activity) throws Exception { - - - Callable ActuallyUpdateStuff = () -> { - return this.getAdapter().UpdateActivity(this, activity); - }; - - return UpdateActivityInternal(activity, onUpdateActivity.iterator(), ActuallyUpdateStuff); - } - - - - /** - * Deletes an existing activity. - * - * @param activityId The ID of the activity to delete. - * @return A task that represents the work queued to execute. - * @throws Exception The HTTP operation failed and the response contained additional information. - */ - public CompletableFuture DeleteActivity(String activityId) throws Exception { - if (StringUtils.isWhitespace(activityId) || activityId == null) - throw new IllegalArgumentException("activityId"); - - return CompletableFuture.runAsync(() -> { - ConversationReference cr = this.GetConversationReference(this.getActivity()); - cr.withActivityId(activityId); - - Runnable ActuallyDeleteStuff = () -> { - try { - this.getAdapter().DeleteActivity(this, cr); - } catch (ExecutionException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed to delete activity %s", e.toString())); - } catch (InterruptedException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed to delete activity %s", e.toString())); - } - return; - }; - - try { - DeleteActivityInternal(cr, onDeleteActivity.iterator(), ActuallyDeleteStuff); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed to delete activity %s", e.getMessage())); - } - return; - - }, executor); - - } - - /** - * Deletes an existing activity. - * - * @param conversationReference The conversation containing the activity to delete. - * @return A task that represents the work queued to execute. - * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. - * The conversation reference's {@link ConversationReference.ActivityId} - * indicates the activity in the conversation to delete. - */ - public void DeleteActivity(ConversationReference conversationReference) throws Exception { - if (conversationReference == null) - throw new IllegalArgumentException("conversationReference"); - - Runnable ActuallyDeleteStuff = () -> { - try { - this.getAdapter().DeleteActivity(this, conversationReference); - return; - } catch (ExecutionException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - throw new RuntimeException("DeleteActivity failed"); - }; - - DeleteActivityInternal(conversationReference, onDeleteActivity.iterator(), ActuallyDeleteStuff); - return ; - } - - private ResourceResponse[] SendActivitiesInternal(List activities, Iterator sendHandlers, Callable callAtBottom) throws Exception { - if (activities == null) - throw new IllegalArgumentException("activities"); - if (sendHandlers == null) - throw new IllegalArgumentException("sendHandlers"); - - if (false == sendHandlers.hasNext()) { // No middleware to run. - if (callAtBottom != null) - return callAtBottom.call(); - return new ResourceResponse[0]; - } - - // Default to "No more Middleware after this". - Callable next = () -> { - // Remove the first item from the list of middleware to call, - // so that the next call just has the remaining items to worry about. - //Iterable remaining = sendHandlers.Skip(1); - //Iterator remaining = sendHandlers.iterator(); - if (sendHandlers.hasNext()) - sendHandlers.next(); - return SendActivitiesInternal(activities, sendHandlers, callAtBottom); - }; - - // Grab the current middleware, which is the 1st element in the array, and execute it - SendActivitiesHandler caller = sendHandlers.next(); - return caller.handle(this, activities, next); - } - - // private async Task UpdateActivityInternal(Activity activity, - // IEnumerable updateHandlers, - // Func> callAtBottom) - // { - // BotAssert.ActivityNotNull(activity); - // if (updateHandlers == null) - // throw new ArgumentException(nameof(updateHandlers)); - // - // if (updateHandlers.Count() == 0) // No middleware to run. - // { - // if (callAtBottom != null) - // { - // return await callAtBottom(); - // } - // - // return null; - // } - // - // /** - // */ Default to "No more Middleware after this". - // */ - // async Task next() - // { - // /** - // */ Remove the first item from the list of middleware to call, - // */ so that the next call just has the remaining items to worry about. - // */ - // IEnumerable remaining = updateHandlers.Skip(1); - // var result = await UpdateActivityInternal(activity, remaining, callAtBottom).ConfigureAwait(false); - // activity.Id = result.Id; - // return result; - // } - // - // /** - // */ Grab the current middleware, which is the 1st element in the array, and execute it - // */ - // UpdateActivityHandler toCall = updateHandlers.First(); - // return await toCall(this, activity, next); - // } - private ResourceResponse UpdateActivityInternal(Activity activity, - Iterator updateHandlers, - Callable callAtBottom) throws Exception { - BotAssert.ActivityNotNull(activity); - if (updateHandlers == null) - throw new IllegalArgumentException("updateHandlers"); - - if (false == updateHandlers.hasNext()) { // No middleware to run. - if (callAtBottom != null) { - return callAtBottom.call(); - } - return null; - } - - // Default to "No more Middleware after this". - Callable next = () -> { - // Remove the first item from the list of middleware to call, - // so that the next call just has the remaining items to worry about. - if (updateHandlers.hasNext()) - updateHandlers.next(); - ResourceResponse result = null; - try { - result = UpdateActivityInternal(activity, updateHandlers, callAtBottom); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Error updating activity: %s", e.toString())); - } - activity.withId(result.id()); - return result; - }; - - // Grab the current middleware, which is the 1st element in the array, and execute it - UpdateActivityHandler toCall = updateHandlers.next(); - return toCall.handle(this, activity, next); - } - - - private void DeleteActivityInternal(ConversationReference cr, - Iterator deleteHandlers, - Runnable callAtBottom) throws Exception { - BotAssert.ConversationReferenceNotNull(cr); - if (deleteHandlers == null) - throw new IllegalArgumentException("deleteHandlers"); - - if (deleteHandlers.hasNext() == false) { // No middleware to run. - if (callAtBottom != null) { - callAtBottom.run(); - } - return; - } - - // Default to "No more Middleware after this". - Runnable next = () -> { - // Remove the first item from the list of middleware to call, - // so that the next call just has the remaining items to worry about. - - //Iterator remaining = (deleteHandlers.hasNext()) ? deleteHandlers.next() : null; - if (deleteHandlers.hasNext()) - deleteHandlers.next(); - - - try { - DeleteActivityInternal(cr, deleteHandlers, callAtBottom); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("DeleteActivityInternal failed"); - } - return; - }; - - // Grab the current middleware, which is the 1st element in the array, and execute it. - DeleteActivityHandler toCall = deleteHandlers.next(); - toCall.handle(this, cr, next); - } - - /** - * Creates a conversation reference from an activity. - * - * @param activity The activity. - * @return A conversation reference for the conversation that contains the activity. - * @throws IllegalArgumentException {@code activity} is {@code null}. - */ - public static ConversationReference GetConversationReference(Activity activity) { - BotAssert.ActivityNotNull(activity); - - ConversationReference r = new ConversationReference() - .withActivityId(activity.id()) - .withUser(activity.from()) - .withBot(activity.recipient()) - .withConversation(activity.conversation()) - .withChannelId(activity.channelId()) - .withServiceUrl(activity.serviceUrl()); - - return r; - } - - /** - * Updates an activity with the delivery information from an existing - * conversation reference. - * - * @param activity The activity to update. - * @param reference The conversation reference. - * @param isIncoming (Optional) {@code true} to treat the activity as an - * incoming activity, where the bot is the recipient; otherwaire {@code false}. - * Default is {@code false}, and the activity will show the bot as the sender. - * Call {@link GetConversationReference(Activity)} on an incoming - * activity to get a conversation reference that you can then use to update an - * outgoing activity with the correct delivery information. - *

The {@link SendActivity(Activity)} and {@link SendActivities(Activity[])} - * methods do this for you.

- */ - public static Activity ApplyConversationReference(Activity activity, ConversationReference reference) { - return ApplyConversationReference(activity, reference, false); - } - - public static Activity ApplyConversationReference(Activity activity, ConversationReference reference, boolean isIncoming) { - activity.withChannelId(reference.channelId()); - activity.withServiceUrl(reference.serviceUrl()); - activity.withConversation(reference.conversation()); - - if (isIncoming) { - activity.withFrom(reference.user()); - activity.withRecipient(reference.bot()); - if (reference.activityId() != null) - activity.withId(reference.activityId()); - } else { // Outgoing - activity.withFrom(reference.bot()); - activity.withRecipient(reference.user()); - if (reference.activityId() != null) - activity.withReplyToId(reference.activityId()); - } - return activity; - } - - public void close() throws Exception { - turnServices.close(); - } -} +package com.microsoft.bot.builder; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import com.microsoft.bot.connector.ExecutorFactory; +import com.microsoft.bot.schema.ActivityImpl; +import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.models.ConversationReference; +import com.microsoft.bot.schema.models.InputHints; +import com.microsoft.bot.schema.models.ResourceResponse; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.*; + +import static com.microsoft.bot.schema.models.ActivityTypes.MESSAGE; +import static com.microsoft.bot.schema.models.ActivityTypes.TRACE; +import static java.util.stream.Collectors.toList; + +/** + * Provides context for a turn of a bot. + * Context provides information needed to process an incoming activity. + * The context object is created by a {@link BotAdapter} and persists for the + * length of the turn. + * {@linkalso Bot} + * {@linkalso Middleware} + */ +public class TurnContextImpl implements TurnContext, AutoCloseable { + private final BotAdapter adapter; + private final ActivityImpl activity; + private Boolean responded = false; + + private final List onSendActivities = new ArrayList(); + private final List onUpdateActivity = new ArrayList(); + private final List onDeleteActivity = new ArrayList(); + + private final TurnContextServiceCollection turnServices; + + /** + * Creates a context object. + * + * @param adapter The adapter creating the context. + * @param activity The incoming activity for the turn; + * or {@code null} for a turn for a proactive message. + * @throws IllegalArgumentException {@code activity} or + * {@code adapter} is {@code null}. + * For use by bot adapter implementations only. + */ + public TurnContextImpl(BotAdapter adapter, ActivityImpl activity) { + if (adapter == null) + throw new IllegalArgumentException("adapter"); + this.adapter = adapter; + if (activity == null) + throw new IllegalArgumentException("activity"); + this.activity = activity; + + turnServices = new TurnContextServiceCollectionImpl(); + } + + + /** + * Adds a response handler for send activity operations. + * + * @param handler The handler to add to the context object. + * @return The updated context object. + * @throws IllegalArgumentException {@code handler} is {@code null}. + * When the context's {@link SendActivity(Activity)} + * or {@link SendActivities(Activity[])} methods are called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + */ + public TurnContextImpl OnSendActivities(SendActivitiesHandler handler) { + if (handler == null) + throw new IllegalArgumentException("handler"); + + this.onSendActivities.add(handler); + return this; + } + + /** + * Adds a response handler for update activity operations. + * + * @param handler The handler to add to the context object. + * @return The updated context object. + * @throws IllegalArgumentException {@code handler} is {@code null}. + * When the context's {@link UpdateActivity(Activity)} is called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + */ + public TurnContextImpl OnUpdateActivity(UpdateActivityHandler handler) { + if (handler == null) + throw new IllegalArgumentException("handler"); + + this.onUpdateActivity.add(handler); + return this; + } + + /** + * Adds a response handler for delete activity operations. + * + * @param handler The handler to add to the context object. + * @return The updated context object. + * @throws IllegalArgumentException {@code handler} is {@code null}. + * When the context's {@link DeleteActivity(string)} is called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + */ + public TurnContextImpl OnDeleteActivity(DeleteActivityHandler handler) { + if (handler == null) + throw new IllegalArgumentException("handler"); + + this.onDeleteActivity.add(handler); + return this; + } + + /** + * Gets the bot adapter that created this context object. + */ + public BotAdapter getAdapter() { + return this.adapter; + } + + /** + * Gets the services registered on this context object. + */ + public TurnContextServiceCollection getServices() { + return this.turnServices; + } + + /** + * Gets the activity associated with this turn; or {@code null} when processing + * a proactive message. + */ + @Override + public Activity getActivity() { + return this.activity; + } + + /** + * Indicates whether at least one response was sent for the current turn. + * + * @return {@code true} if at least one response was sent for the current turn. + * @throws IllegalArgumentException You attempted to set the value to {@code false}. + */ + public boolean getResponded() { + return this.responded; + } + + public void setResponded(boolean responded) { + if (responded == false) { + throw new IllegalArgumentException("TurnContext: cannot set 'responded' to a value of 'false'."); + } + this.responded = true; + } + + /** + * Sends a message activity to the sender of the incoming activity. + * + * @param textReplyToSend The text of the message to send. + * @param speak Optional, text to be spoken by your bot on a speech-enabled + * channel. + * @param inputHint Optional, indicates whether your bot is accepting, + * expecting, or ignoring user input after the message is delivered to the client. + * One of: "acceptingInput", "ignoringInput", or "expectingInput". + * Default is null. + * @return A task that represents the work queued to execute. + * @throws IllegalArgumentException {@code textReplyToSend} is {@code null} or whitespace. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

See the channel's documentation for limits imposed upon the contents of + * {@code textReplyToSend}.

+ *

To control various characteristics of your bot's speech such as voice, + * rate, volume, pronunciation, and pitch, specify {@code speak} in + * Speech Synthesis Markup Language (SSML) format.

+ */ + @Override + public ResourceResponse SendActivity(String textReplyToSend) throws Exception { + return SendActivity(textReplyToSend, null, null); + } + + @Override + public ResourceResponse SendActivity(String textReplyToSend, String speak) throws Exception { + return SendActivity(textReplyToSend, speak, null); + } + + @Override + public ResourceResponse SendActivity(String textReplyToSend, String speak, String inputHint) throws Exception { + if (StringUtils.isEmpty(textReplyToSend)) + throw new IllegalArgumentException("textReplyToSend"); + + ActivityImpl activityToSend = (ActivityImpl) new ActivityImpl() + .withType(MESSAGE) + .withText(textReplyToSend); + if (speak != null) + activityToSend.withSpeak(speak); + + if (StringUtils.isNotEmpty(inputHint)) + activityToSend.withInputHint(InputHints.fromString(inputHint)); + + return SendActivity(activityToSend); + } + + /** + * Sends an activity to the sender of the incoming activity. + * + * @param activity The activity to send. + * @return A task that represents the work queued to execute. + * @throws IllegalArgumentException {@code activity} is {@code null}. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + */ + @Override + public ResourceResponse SendActivity(Activity activity) throws Exception { + if (activity == null) + throw new IllegalArgumentException("activity"); + + System.out.printf("In SENDEACTIVITYASYNC:"); + System.out.flush(); + Activity[] activities = {activity}; + ResourceResponse[] responses; + try { + responses = SendActivities(activities); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("TurnContext:SendActivity fail %s", e.toString())); + } + if (responses == null || responses.length == 0) { + // It's possible an interceptor prevented the activity from having been sent. + // Just return an empty response in that case. + return null; + } else { + return responses[0]; + } + + } + + /** + * Sends a set of activities to the sender of the incoming activity. + * + * @param activities The activities to send. + * @return A task that represents the work queued to execute. + * If the activities are successfully sent, the task result contains + * an array of {@link ResourceResponse} objects containing the IDs that + * the receiving channel assigned to the activities. + */ + @Override + public ResourceResponse[] SendActivities(Activity[] activities) throws Exception { + // Bind the relevant Conversation Reference properties, such as URLs and + // ChannelId's, to the activities we're about to send. + ConversationReference cr = GetConversationReference(this.activity); + for (Activity a : activities) { + ApplyConversationReference(a, cr); + } + + // Convert the IActivities to Activies. + // Activity[] activityArray = Array.ConvertAll(activities, (input) => (Activity)input); + List activityArray = Arrays.stream(activities).map(input -> (Activity) input).collect(toList()); + + + // Create the list used by the recursive methods. + List activityList = new ArrayList(activityArray); + + Callable ActuallySendStuff = () -> { + // Are the any non-trace activities to send? + // The thinking here is that a Trace event isn't user relevant data + // so the "Responded" flag should not be set by Trace messages being + // sent out. + boolean sentNonTraceActivities = false; + if (!activityList.stream().anyMatch((a) -> a.type() == TRACE)) { + sentNonTraceActivities = true; + } + // Send from the list, which may have been manipulated via the event handlers. + // Note that 'responses' was captured from the root of the call, and will be + // returned to the original caller. + ResourceResponse[] responses = new ResourceResponse[0]; + responses = this.getAdapter().SendActivities(this, activityList.toArray(new ActivityImpl[activityList.size()])); + if (responses != null && responses.length == activityList.size()) { + // stitch up activity ids + for (int i = 0; i < responses.length; i++) { + ResourceResponse response = responses[i]; + Activity activity = activityList.get(i); + activity.withId(response.id()); + } + } + + // If we actually sent something (that's not Trace), set the flag. + if (sentNonTraceActivities) { + this.setResponded(true); + } + return responses; + }; + + List act_list = new ArrayList<>(activityList); + return SendActivitiesInternal(act_list, onSendActivities.iterator(), ActuallySendStuff); + } + + /** + * Replaces an existing activity. + * + * @param activity New replacement activity. + * @return A task that represents the work queued to execute. + * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. + * @throws System.AggregateException One or more exceptions occurred during the operation. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

Before calling this, set the ID of the replacement activity to the ID + * of the activity to replace.

+ */ + @Override + public ResourceResponse UpdateActivity(Activity activity) throws Exception { + + + Callable ActuallyUpdateStuff = () -> { + return this.getAdapter().UpdateActivity(this, activity); + }; + + return UpdateActivityInternal(activity, onUpdateActivity.iterator(), ActuallyUpdateStuff); + } + + + + /** + * Deletes an existing activity. + * + * @param activityId The ID of the activity to delete. + * @return A task that represents the work queued to execute. + * @throws Exception The HTTP operation failed and the response contained additional information. + */ + public CompletableFuture DeleteActivity(String activityId) throws Exception { + if (StringUtils.isWhitespace(activityId) || activityId == null) + throw new IllegalArgumentException("activityId"); + + return CompletableFuture.runAsync(() -> { + ConversationReference cr = this.GetConversationReference(this.getActivity()); + cr.withActivityId(activityId); + + Runnable ActuallyDeleteStuff = () -> { + try { + this.getAdapter().DeleteActivity(this, cr); + } catch (ExecutionException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Failed to delete activity %s", e.toString())); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Failed to delete activity %s", e.toString())); + } + return; + }; + + try { + DeleteActivityInternal(cr, onDeleteActivity.iterator(), ActuallyDeleteStuff); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Failed to delete activity %s", e.getMessage())); + } + return; + + }, ExecutorFactory.getExecutor()); + + } + + /** + * Deletes an existing activity. + * + * @param conversationReference The conversation containing the activity to delete. + * @return A task that represents the work queued to execute. + * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. + * The conversation reference's {@link ConversationReference.ActivityId} + * indicates the activity in the conversation to delete. + */ + public void DeleteActivity(ConversationReference conversationReference) throws Exception { + if (conversationReference == null) + throw new IllegalArgumentException("conversationReference"); + + Runnable ActuallyDeleteStuff = () -> { + try { + this.getAdapter().DeleteActivity(this, conversationReference); + return; + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + throw new RuntimeException("DeleteActivity failed"); + }; + + DeleteActivityInternal(conversationReference, onDeleteActivity.iterator(), ActuallyDeleteStuff); + return ; + } + + private ResourceResponse[] SendActivitiesInternal(List activities, Iterator sendHandlers, Callable callAtBottom) throws Exception { + if (activities == null) + throw new IllegalArgumentException("activities"); + if (sendHandlers == null) + throw new IllegalArgumentException("sendHandlers"); + + if (false == sendHandlers.hasNext()) { // No middleware to run. + if (callAtBottom != null) + return callAtBottom.call(); + return new ResourceResponse[0]; + } + + // Default to "No more Middleware after this". + Callable next = () -> { + // Remove the first item from the list of middleware to call, + // so that the next call just has the remaining items to worry about. + //Iterable remaining = sendHandlers.Skip(1); + //Iterator remaining = sendHandlers.iterator(); + if (sendHandlers.hasNext()) + sendHandlers.next(); + return SendActivitiesInternal(activities, sendHandlers, callAtBottom); + }; + + // Grab the current middleware, which is the 1st element in the array, and execute it + SendActivitiesHandler caller = sendHandlers.next(); + return caller.handle(this, activities, next); + } + + // private async Task UpdateActivityInternal(Activity activity, + // IEnumerable updateHandlers, + // Func> callAtBottom) + // { + // BotAssert.ActivityNotNull(activity); + // if (updateHandlers == null) + // throw new ArgumentException(nameof(updateHandlers)); + // + // if (updateHandlers.Count() == 0) // No middleware to run. + // { + // if (callAtBottom != null) + // { + // return await callAtBottom(); + // } + // + // return null; + // } + // + // /** + // */ Default to "No more Middleware after this". + // */ + // async Task next() + // { + // /** + // */ Remove the first item from the list of middleware to call, + // */ so that the next call just has the remaining items to worry about. + // */ + // IEnumerable remaining = updateHandlers.Skip(1); + // var result = await UpdateActivityInternal(activity, remaining, callAtBottom).ConfigureAwait(false); + // activity.Id = result.Id; + // return result; + // } + // + // /** + // */ Grab the current middleware, which is the 1st element in the array, and execute it + // */ + // UpdateActivityHandler toCall = updateHandlers.First(); + // return await toCall(this, activity, next); + // } + private ResourceResponse UpdateActivityInternal(Activity activity, + Iterator updateHandlers, + Callable callAtBottom) throws Exception { + BotAssert.ActivityNotNull(activity); + if (updateHandlers == null) + throw new IllegalArgumentException("updateHandlers"); + + if (false == updateHandlers.hasNext()) { // No middleware to run. + if (callAtBottom != null) { + return callAtBottom.call(); + } + return null; + } + + // Default to "No more Middleware after this". + Callable next = () -> { + // Remove the first item from the list of middleware to call, + // so that the next call just has the remaining items to worry about. + if (updateHandlers.hasNext()) + updateHandlers.next(); + ResourceResponse result = null; + try { + result = UpdateActivityInternal(activity, updateHandlers, callAtBottom); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Error updating activity: %s", e.toString())); + } + activity.withId(result.id()); + return result; + }; + + // Grab the current middleware, which is the 1st element in the array, and execute it + UpdateActivityHandler toCall = updateHandlers.next(); + return toCall.handle(this, activity, next); + } + + + private void DeleteActivityInternal(ConversationReference cr, + Iterator deleteHandlers, + Runnable callAtBottom) throws Exception { + BotAssert.ConversationReferenceNotNull(cr); + if (deleteHandlers == null) + throw new IllegalArgumentException("deleteHandlers"); + + if (deleteHandlers.hasNext() == false) { // No middleware to run. + if (callAtBottom != null) { + callAtBottom.run(); + } + return; + } + + // Default to "No more Middleware after this". + Runnable next = () -> { + // Remove the first item from the list of middleware to call, + // so that the next call just has the remaining items to worry about. + + //Iterator remaining = (deleteHandlers.hasNext()) ? deleteHandlers.next() : null; + if (deleteHandlers.hasNext()) + deleteHandlers.next(); + + + try { + DeleteActivityInternal(cr, deleteHandlers, callAtBottom); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("DeleteActivityInternal failed"); + } + return; + }; + + // Grab the current middleware, which is the 1st element in the array, and execute it. + DeleteActivityHandler toCall = deleteHandlers.next(); + toCall.handle(this, cr, next); + } + + /** + * Creates a conversation reference from an activity. + * + * @param activity The activity. + * @return A conversation reference for the conversation that contains the activity. + * @throws IllegalArgumentException {@code activity} is {@code null}. + */ + public static ConversationReference GetConversationReference(Activity activity) { + BotAssert.ActivityNotNull(activity); + + ConversationReference r = new ConversationReference() + .withActivityId(activity.id()) + .withUser(activity.from()) + .withBot(activity.recipient()) + .withConversation(activity.conversation()) + .withChannelId(activity.channelId()) + .withServiceUrl(activity.serviceUrl()); + + return r; + } + + /** + * Updates an activity with the delivery information from an existing + * conversation reference. + * + * @param activity The activity to update. + * @param reference The conversation reference. + * @param isIncoming (Optional) {@code true} to treat the activity as an + * incoming activity, where the bot is the recipient; otherwaire {@code false}. + * Default is {@code false}, and the activity will show the bot as the sender. + * Call {@link GetConversationReference(Activity)} on an incoming + * activity to get a conversation reference that you can then use to update an + * outgoing activity with the correct delivery information. + *

The {@link SendActivity(Activity)} and {@link SendActivities(Activity[])} + * methods do this for you.

+ */ + public static Activity ApplyConversationReference(Activity activity, ConversationReference reference) { + return ApplyConversationReference(activity, reference, false); + } + + public static Activity ApplyConversationReference(Activity activity, ConversationReference reference, boolean isIncoming) { + activity.withChannelId(reference.channelId()); + activity.withServiceUrl(reference.serviceUrl()); + activity.withConversation(reference.conversation()); + + if (isIncoming) { + activity.withFrom(reference.user()); + activity.withRecipient(reference.bot()); + if (reference.activityId() != null) + activity.withId(reference.activityId()); + } else { // Outgoing + activity.withFrom(reference.bot()); + activity.withRecipient(reference.user()); + if (reference.activityId() != null) + activity.withReplyToId(reference.activityId()); + } + return activity; + } + + public void close() throws Exception { + turnServices.close(); + } +} diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java index 16d3029f5..9c29fbe77 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java @@ -1,109 +1,110 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.builder.adapters.TestAdapter; -import com.microsoft.bot.builder.adapters.TestFlow; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -public class CatchException_MiddlewareTest { - - @Test - public void CatchException_TestMiddleware_TestStackedErrorMiddleware() throws ExecutionException, InterruptedException { - - TestAdapter adapter = new TestAdapter() - .Use(new CatchExceptionMiddleware(new CallOnException() { - @Override - public CompletableFuture apply(TurnContext context, T t) throws Exception { - return CompletableFuture.runAsync(() -> { - Activity activity = context.getActivity(); - if (activity instanceof ActivityImpl) { - try { - context.SendActivity(((ActivityImpl) activity).CreateReply(t.toString())); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("CatchException_TestMiddleware_TestStackedErrorMiddleware:SendActivity failed %s", e.toString())); - } - } else - Assert.assertTrue("Test was built for ActivityImpl", false); - - }); - - } - }, Exception.class)) - // Add middleware to catch NullReferenceExceptions before throwing up to the general exception instance - .Use(new CatchExceptionMiddleware(new CallOnException() { - @Override - public CompletableFuture apply(TurnContext context, T t) throws Exception { - context.SendActivity("Sorry - Null Reference Exception"); - return CompletableFuture.completedFuture(null); - } - }, NullPointerException.class)); - - - new TestFlow(adapter, (context) -> - { - - if (context.getActivity().text() == "foo") { - try { - context.SendActivity(context.getActivity().text()); - } catch (Exception e) { - e.printStackTrace(); - } - } - if (context.getActivity().text() == "UnsupportedOperationException") { - throw new UnsupportedOperationException("Test"); - } - - } - ) - .Send("foo") - .AssertReply("foo", "passthrough") - .Send("UnsupportedOperationException") - .AssertReply("Test") - .StartTest(); - - } - -/* @Test - // [TestCategory("Middleware")] - public void CatchException_TestMiddleware_SpecificExceptionType() -{ - TestAdapter adapter = new TestAdapter() - .Use(new CatchExceptionMiddleware((context, exception) => - { - context.SendActivity("Generic Exception Caught"); - return CompletableFuture.CompletedTask; - })) - .Use(new CatchExceptionMiddleware((context, exception) => - { - context.SendActivity(exception.Message); - return CompletableFuture.CompletedTask; - })); - - - await new TestFlow(adapter, (context) => - { - if (context.Activity.AsMessageActivity().Text == "foo") - { - context.SendActivity(context.Activity.AsMessageActivity().Text); - } - - if (context.Activity.AsMessageActivity().Text == "NullReferenceException") - { - throw new NullReferenceException("Test"); - } - - return CompletableFuture.CompletedTask; - }) - .Send("foo") - .AssertReply("foo", "passthrough") - .Send("NullReferenceException") - .AssertReply("Test") - .StartTest(); -}*/ -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.builder.adapters.TestAdapter; +import com.microsoft.bot.builder.adapters.TestFlow; +import com.microsoft.bot.connector.ExecutorFactory; +import com.microsoft.bot.schema.ActivityImpl; +import com.microsoft.bot.schema.models.Activity; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class CatchException_MiddlewareTest { + + @Test + public void CatchException_TestMiddleware_TestStackedErrorMiddleware() throws ExecutionException, InterruptedException { + + TestAdapter adapter = new TestAdapter() + .Use(new CatchExceptionMiddleware(new CallOnException() { + @Override + public CompletableFuture apply(TurnContext context, T t) throws Exception { + return CompletableFuture.runAsync(() -> { + Activity activity = context.getActivity(); + if (activity instanceof ActivityImpl) { + try { + context.SendActivity(((ActivityImpl) activity).CreateReply(t.toString())); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("CatchException_TestMiddleware_TestStackedErrorMiddleware:SendActivity failed %s", e.toString())); + } + } else + Assert.assertTrue("Test was built for ActivityImpl", false); + + }, ExecutorFactory.getExecutor()); + + } + }, Exception.class)) + // Add middleware to catch NullReferenceExceptions before throwing up to the general exception instance + .Use(new CatchExceptionMiddleware(new CallOnException() { + @Override + public CompletableFuture apply(TurnContext context, T t) throws Exception { + context.SendActivity("Sorry - Null Reference Exception"); + return CompletableFuture.completedFuture(null); + } + }, NullPointerException.class)); + + + new TestFlow(adapter, (context) -> + { + + if (context.getActivity().text() == "foo") { + try { + context.SendActivity(context.getActivity().text()); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (context.getActivity().text() == "UnsupportedOperationException") { + throw new UnsupportedOperationException("Test"); + } + + } + ) + .Send("foo") + .AssertReply("foo", "passthrough") + .Send("UnsupportedOperationException") + .AssertReply("Test") + .StartTest(); + + } + +/* @Test + // [TestCategory("Middleware")] + public void CatchException_TestMiddleware_SpecificExceptionType() +{ + TestAdapter adapter = new TestAdapter() + .Use(new CatchExceptionMiddleware((context, exception) => + { + context.SendActivity("Generic Exception Caught"); + return CompletableFuture.CompletedTask; + })) + .Use(new CatchExceptionMiddleware((context, exception) => + { + context.SendActivity(exception.Message); + return CompletableFuture.CompletedTask; + })); + + + await new TestFlow(adapter, (context) => + { + if (context.Activity.AsMessageActivity().Text == "foo") + { + context.SendActivity(context.Activity.AsMessageActivity().Text); + } + + if (context.Activity.AsMessageActivity().Text == "NullReferenceException") + { + throw new NullReferenceException("Test"); + } + + return CompletableFuture.CompletedTask; + }) + .Send("foo") + .AssertReply("foo", "passthrough") + .Send("NullReferenceException") + .AssertReply("Test") + .StartTest(); +}*/ +} diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/DictionaryStorage.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/DictionaryStorage.java index 289ced22c..b8525b1c3 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/DictionaryStorage.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/DictionaryStorage.java @@ -1,129 +1,130 @@ -package com.microsoft.bot.builder; - -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 com.fasterxml.jackson.databind.node.ObjectNode; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import static java.util.concurrent.CompletableFuture.completedFuture; - -/** - * Models IStorage around a dictionary - */ -public class DictionaryStorage implements Storage { - private static ObjectMapper objectMapper; - - // TODO: Object needs to be defined - private final Map memory; - private final Object syncroot = new Object(); - private int _eTag = 0; - private final String typeNameForNonEntity = "__type_name_"; - - public DictionaryStorage() { - this(null); - } - public DictionaryStorage(Map dictionary ) { - DictionaryStorage.objectMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .findAndRegisterModules(); - this.memory = (dictionary != null) ? dictionary : new HashMap(); - } - - public CompletableFuture Delete(String[] keys) { - synchronized (this.syncroot) { - for (String key : keys) { - Object o = this.memory.get(key); - this.memory.remove(o); - } - } - return completedFuture(null); - } - - @Override - public CompletableFuture> Read(String[] keys) throws JsonProcessingException { - return CompletableFuture.supplyAsync(() -> { - Map storeItems = new HashMap(keys.length); - synchronized (this.syncroot) { - for (String key : keys) { - if (this.memory.containsKey(key)) { - Object state = this.memory.get(key); - if (state != null) { - try { - if (!(state instanceof JsonNode)) - throw new RuntimeException("DictionaryRead failed: entry not JsonNode"); - JsonNode stateNode = (JsonNode) state; - // Check if type info is set for the class - if (!(stateNode.hasNonNull(this.typeNameForNonEntity))) { - throw new RuntimeException(String.format("DictionaryRead failed: Type info not present")); - } - String clsName = stateNode.get(this.typeNameForNonEntity).textValue(); - - // Load the class info - Class cls; - try { - cls = Class.forName(clsName); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("DictionaryRead failed: Could not load class %s", clsName)); - } - - // Populate dictionary - storeItems.put(key,DictionaryStorage.objectMapper.treeToValue(stateNode, cls )); - } catch (JsonProcessingException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("DictionaryRead failed: %s", e.toString())); - } - } - } - - } - } - - return storeItems; - }); - } - - @Override - public CompletableFuture Write(Map changes) throws Exception { - synchronized (this.syncroot) { - for (Map.Entry change : changes.entrySet()) { - Object newValue = change.getValue(); - - String oldStateETag = null; // default(string); - if (this.memory.containsValue(change.getKey())) { - Map oldState = (Map) this.memory.get(change.getKey()); - if (oldState.containsValue("eTag")) { - Map.Entry eTagToken = (Map.Entry) oldState.get("eTag"); - oldStateETag = (String) eTagToken.getValue(); - } - - } - // Dictionary stores Key:JsonNode (with type information held within the JsonNode) - JsonNode newState = DictionaryStorage.objectMapper.valueToTree(newValue); - ((ObjectNode)newState).put(this.typeNameForNonEntity, newValue.getClass().getTypeName()); - - // Set ETag if applicable - if (newValue instanceof StoreItem) { - StoreItem newStoreItem = (StoreItem) newValue; - if(oldStateETag != null && newStoreItem.geteTag() != "*" && - newStoreItem.geteTag() != oldStateETag) { - throw new Exception(String.format("Etag conflict.\r\n\r\nOriginal: %s\r\nCurrent: %s", - newStoreItem.geteTag(), oldStateETag)); - } - Integer newTag = _eTag++; - ((ObjectNode)newState).put("eTag", newTag.toString()); - } - - this.memory.put((String)change.getKey(), newState); - } - } - return completedFuture(null); - } - -} - +package com.microsoft.bot.builder; + +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 com.fasterxml.jackson.databind.node.ObjectNode; +import com.microsoft.bot.connector.ExecutorFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static java.util.concurrent.CompletableFuture.completedFuture; + +/** + * Models IStorage around a dictionary + */ +public class DictionaryStorage implements Storage { + private static ObjectMapper objectMapper; + + // TODO: Object needs to be defined + private final Map memory; + private final Object syncroot = new Object(); + private int _eTag = 0; + private final String typeNameForNonEntity = "__type_name_"; + + public DictionaryStorage() { + this(null); + } + public DictionaryStorage(Map dictionary ) { + DictionaryStorage.objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .findAndRegisterModules(); + this.memory = (dictionary != null) ? dictionary : new HashMap(); + } + + public CompletableFuture Delete(String[] keys) { + synchronized (this.syncroot) { + for (String key : keys) { + Object o = this.memory.get(key); + this.memory.remove(o); + } + } + return completedFuture(null); + } + + @Override + public CompletableFuture> Read(String[] keys) throws JsonProcessingException { + return CompletableFuture.supplyAsync(() -> { + Map storeItems = new HashMap(keys.length); + synchronized (this.syncroot) { + for (String key : keys) { + if (this.memory.containsKey(key)) { + Object state = this.memory.get(key); + if (state != null) { + try { + if (!(state instanceof JsonNode)) + throw new RuntimeException("DictionaryRead failed: entry not JsonNode"); + JsonNode stateNode = (JsonNode) state; + // Check if type info is set for the class + if (!(stateNode.hasNonNull(this.typeNameForNonEntity))) { + throw new RuntimeException(String.format("DictionaryRead failed: Type info not present")); + } + String clsName = stateNode.get(this.typeNameForNonEntity).textValue(); + + // Load the class info + Class cls; + try { + cls = Class.forName(clsName); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("DictionaryRead failed: Could not load class %s", clsName)); + } + + // Populate dictionary + storeItems.put(key,DictionaryStorage.objectMapper.treeToValue(stateNode, cls )); + } catch (JsonProcessingException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("DictionaryRead failed: %s", e.toString())); + } + } + } + + } + } + + return storeItems; + }, ExecutorFactory.getExecutor()); + } + + @Override + public CompletableFuture Write(Map changes) throws Exception { + synchronized (this.syncroot) { + for (Map.Entry change : changes.entrySet()) { + Object newValue = change.getValue(); + + String oldStateETag = null; // default(string); + if (this.memory.containsValue(change.getKey())) { + Map oldState = (Map) this.memory.get(change.getKey()); + if (oldState.containsValue("eTag")) { + Map.Entry eTagToken = (Map.Entry) oldState.get("eTag"); + oldStateETag = (String) eTagToken.getValue(); + } + + } + // Dictionary stores Key:JsonNode (with type information held within the JsonNode) + JsonNode newState = DictionaryStorage.objectMapper.valueToTree(newValue); + ((ObjectNode)newState).put(this.typeNameForNonEntity, newValue.getClass().getTypeName()); + + // Set ETag if applicable + if (newValue instanceof StoreItem) { + StoreItem newStoreItem = (StoreItem) newValue; + if(oldStateETag != null && newStoreItem.geteTag() != "*" && + newStoreItem.geteTag() != oldStateETag) { + throw new Exception(String.format("Etag conflict.\r\n\r\nOriginal: %s\r\nCurrent: %s", + newStoreItem.geteTag(), oldStateETag)); + } + Integer newTag = _eTag++; + ((ObjectNode)newState).put("eTag", newTag.toString()); + } + + this.memory.put((String)change.getKey(), newState); + } + } + return completedFuture(null); + } + +} + diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java index c68956c89..e48a727bd 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java @@ -1,468 +1,469 @@ -package com.microsoft.bot.builder.adapters; - -import com.microsoft.bot.builder.TurnContext; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import org.joda.time.DateTime; -import org.junit.Assert; - -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.concurrent.*; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import static java.util.concurrent.CompletableFuture.completedFuture; - -public class TestFlow { - final TestAdapter adapter; - CompletableFuture testTask; - Consumer callback; - - ArrayList> tasks = new ArrayList>(); - ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() - { - @Override - public ForkJoinWorkerThread newThread(ForkJoinPool pool) - { - final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName("TestFlow-" + worker.getPoolIndex()); - return worker; - } - }; - - ExecutorService executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), factory, null, true); - - - public TestFlow(TestAdapter adapter) { - this(adapter, null); - } - - public TestFlow(TestAdapter adapter, Consumer callback) { - this.adapter = adapter; - this.callback = callback; - this.testTask = completedFuture(null); - } - - - public TestFlow(Supplier testTask, TestFlow flow) { - this.tasks = flow.tasks; - if (testTask != null) - this.tasks.add(testTask); - this.callback = flow.callback; - this.adapter = flow.adapter; - } - - - /** - * Start the execution of the test flow - * - * @return - */ - public String StartTest() throws ExecutionException, InterruptedException { - - System.out.printf("+------------------------------------------+\n"); - int count = 0; - for (Supplier task : this.tasks) { - System.out.printf("| Running task %s of %s\n", count++, this.tasks.size()); - String result = null; - result = task.get(); - System.out.printf("| --> Result: %s", result); - System.out.flush(); - } - System.out.printf("+------------------------------------------+\n"); - return "Completed"; - - } - - /** - * Send a message from the user to the bot - * - * @param userSays - * @return - */ - public TestFlow Send(String userSays) throws IllegalArgumentException { - if (userSays == null) - throw new IllegalArgumentException("You have to pass a userSays parameter"); - - // Function - return new TestFlow((() -> { - System.out.print(String.format("USER SAYS: %s (Thread Id: %s)\n", userSays, Thread.currentThread().getId())); - System.out.flush(); - try { - this.adapter.SendTextToBot(userSays, this.callback); - return "Successfully sent " + userSays; - } catch (Exception e) { - Assert.fail(e.getMessage()); - return e.getMessage(); - } - }), this); - } - - /** - * Send an activity from the user to the bot - * - * @param userActivity - * @return - */ - public TestFlow Send(Activity userActivity) { - if (userActivity == null) - throw new IllegalArgumentException("You have to pass an Activity"); - - return new TestFlow((() -> { - System.out.printf("TestFlow(%s): Send with User Activity! %s", Thread.currentThread().getId(), userActivity.text()); - System.out.flush(); - - - try { - this.adapter.ProcessActivity((ActivityImpl) userActivity, this.callback); - return "TestFlow: Send() -> ProcessActivity: " + userActivity.text(); - } catch (Exception e) { - return e.getMessage(); - - } - - }), this); - } - - /** - * Delay for time period - * - * @param ms - * @return - */ - public TestFlow Delay(int ms) { - return new TestFlow(() -> - { - System.out.printf("TestFlow(%s): Delay(%s ms) called. ", Thread.currentThread().getId(), ms); - System.out.flush(); - try { - Thread.sleep((int) ms); - } catch (InterruptedException e) { - return e.getMessage(); - } - return null; - }, this); - } - - /** - * Assert that reply is expected text - * - * @param expected - * @param description - * @param timeout - * @return - */ - public TestFlow AssertReply(String expected) { - return this.AssertReply(expected, null, 3000); - } - - public TestFlow AssertReply(String expected, String description) { - return this.AssertReply(expected, description, 3000); - } - - public TestFlow AssertReply(String expected, String description, int timeout) { - return this.AssertReply(this.adapter.MakeActivity(expected), description, timeout); - } - - /** - * Assert that the reply is expected activity - * - * @param expected - * @param description - * @param timeout - * @return - */ - public TestFlow AssertReply(Activity expected) { - String description = Thread.currentThread().getStackTrace()[1].getMethodName(); - return AssertReply(expected, description, 3000); - } - - public TestFlow AssertReply(Activity expected, String description, int timeout) { - if (description == null) - description = Thread.currentThread().getStackTrace()[1].getMethodName(); - String finalDescription = description; - return this.AssertReply((reply) -> { - if (expected.type() != reply.type()) - return String.format("%s: Type should match", finalDescription); - if (expected.text().equals(reply.text())) { - if (finalDescription == null) - return String.format("Expected:%s\nReceived:{reply.AsMessageActivity().Text}", expected.text()); - else - return String.format("%s: Text should match", finalDescription); - } - // TODO, expand this to do all properties set on expected - return null; - }, description, timeout); - } - - /** - * Assert that the reply matches a custom validation routine - * - * @param validateActivity - * @param description - * @param timeout - * @return - */ - public TestFlow AssertReply(Function validateActivity) { - String description = Thread.currentThread().getStackTrace()[1].getMethodName(); - return AssertReply(validateActivity, description, 3000); - } - - public TestFlow AssertReply(Function validateActivity, String description) { - return AssertReply(validateActivity, description, 3000); - } - - public TestFlow AssertReply(Function validateActivity, String description, int timeout) { - return new TestFlow(() -> { - System.out.println(String.format("AssertReply: Starting loop : %s (Thread:%s)", description, Thread.currentThread().getId())); - System.out.flush(); - - int finalTimeout = Integer.MAX_VALUE; - if (isDebug()) - finalTimeout = Integer.MAX_VALUE; - - DateTime start = DateTime.now(); - while (true) { - DateTime current = DateTime.now(); - - if ((current.getMillis() - start.getMillis()) > (long) finalTimeout) { - System.out.println("AssertReply: Timeout!\n"); - System.out.flush(); - return String.format("%d ms Timed out waiting for:'%s'", finalTimeout, description); - } - -// System.out.println("Before GetNextReply\n"); -// System.out.flush(); - - Activity replyActivity = this.adapter.GetNextReply(); -// System.out.println("After GetNextReply\n"); -// System.out.flush(); - - if (replyActivity != null) { - System.out.printf("AssertReply(tid:%s): Received Reply: %s ", Thread.currentThread().getId(), (replyActivity.text() == null) ? "No Text set" : replyActivity.text()); - System.out.flush(); - System.out.printf("=============\n From: %s\n To:%s\n ==========\n", (replyActivity.from() == null) ? "No from set" : replyActivity.from().name(), - (replyActivity.recipient() == null) ? "No recipient set" : replyActivity.recipient().name()); - System.out.flush(); - - // if we have a reply - return validateActivity.apply(replyActivity); - } else { - System.out.printf("AssertReply(tid:%s): Waiting..\n", Thread.currentThread().getId()); - System.out.flush(); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - }, this); - } - - // Hack to determine if debugger attached.. - public boolean isDebug() { - for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) { - if (arg.contains("jdwp=")) { - return true; - } - } - return false; - } - - - /** - * @param userSays - * @param expected - * @return - */ - public TestFlow Turn(String userSays, String expected, String description, int timeout) { - String result = null; - try { - - result = CompletableFuture.supplyAsync(() -> { // Send the message - - if (userSays == null) - throw new IllegalArgumentException("You have to pass a userSays parameter"); - - System.out.print(String.format("TestTurn(%s): USER SAYS: %s \n", Thread.currentThread().getId(), userSays)); - System.out.flush(); - - try { - this.adapter.SendTextToBot(userSays, this.callback); - return null; - } catch (Exception e) { - return e.getMessage(); - } - - }) - .thenApply(arg -> { // Assert Reply - int finalTimeout = Integer.MAX_VALUE; - if (isDebug()) - finalTimeout = Integer.MAX_VALUE; - Function validateActivity = activity -> { - if (activity.text().equals(expected)) { - System.out.println(String.format("TestTurn(tid:%s): Validated text is: %s", Thread.currentThread().getId(), expected)); - System.out.flush(); - - return "SUCCESS"; - } - System.out.println(String.format("TestTurn(tid:%s): Failed validate text is: %s", Thread.currentThread().getId(), expected)); - System.out.flush(); - - return String.format("FAIL: %s received in Activity.text (%s expected)", activity.text(), expected); - }; - - - System.out.println(String.format("TestTurn(tid:%s): Started receive loop: %s", Thread.currentThread().getId(), description)); - System.out.flush(); - DateTime start = DateTime.now(); - while (true) { - DateTime current = DateTime.now(); - - if ((current.getMillis() - start.getMillis()) > (long) finalTimeout) - return String.format("TestTurn: %d ms Timed out waiting for:'%s'", finalTimeout, description); - - - Activity replyActivity = this.adapter.GetNextReply(); - - - if (replyActivity != null) { - // if we have a reply - System.out.println(String.format("TestTurn(tid:%s): Received Reply: %s", - Thread.currentThread().getId(), - String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.recipient().name(), replyActivity.from().name(), replyActivity.text()) - )); - System.out.flush(); - return validateActivity.apply(replyActivity); - } else { - System.out.println(String.format("TestTurn(tid:%s): No reply..", Thread.currentThread().getId())); - System.out.flush(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - } - }) - .get(timeout, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - e.printStackTrace(); - } - return this; - - } - - /** - * Say() -> shortcut for .Send(user).AssertReply(Expected) - * - * @param userSays - * @param expected - * @param description - * @param timeout - * @return - */ - public TestFlow Test(String userSays, String expected) { - return Test(userSays, expected, null, 3000); - } - - public TestFlow Test(String userSays, String expected, String description) { - return Test(userSays, expected, description, 3000); - } - - public TestFlow Test(String userSays, String expected, String description, int timeout) { - if (expected == null) - throw new IllegalArgumentException("expected"); - - return this.Send(userSays) - .AssertReply(expected, description, timeout); - } - - /** - * Test() -> shortcut for .Send(user).AssertReply(Expected) - * - * @param userSays - * @param expected - * @param description - * @param timeout - * @return - */ - public TestFlow Test(String userSays, Activity expected) { - return Test(userSays, expected, null, 3000); - } - - public TestFlow Test(String userSays, Activity expected, String description) { - return Test(userSays, expected, description, 3000); - } - - public TestFlow Test(String userSays, Activity expected, String description, int timeout) { - if (expected == null) - throw new IllegalArgumentException("expected"); - - return this.Send(userSays) - .AssertReply(expected, description, timeout); - } - - /** - * Say() -> shortcut for .Send(user).AssertReply(Expected) - * - * @param userSays - * @param expected - * @param description - * @param timeout - * @return - */ - public TestFlow Test(String userSays, Function expected) { - return Test(userSays, expected, null, 3000); - } - - public TestFlow Test(String userSays, Function expected, String description) { - return Test(userSays, expected, description, 3000); - } - - public TestFlow Test(String userSays, Function expected, String description, int timeout) { - if (expected == null) - throw new IllegalArgumentException("expected"); - - return this.Send(userSays) - .AssertReply(expected, description, timeout); - } - - /** - * Assert that reply is one of the candidate responses - * - * @param candidates - * @param description - * @param timeout - * @return - */ - public TestFlow AssertReplyOneOf(String[] candidates) { - return AssertReplyOneOf(candidates, null, 3000); - } - - public TestFlow AssertReplyOneOf(String[] candidates, String description) { - return AssertReplyOneOf(candidates, description, 3000); - } - - public TestFlow AssertReplyOneOf(String[] candidates, String description, int timeout) { - if (candidates == null) - throw new IllegalArgumentException("candidates"); - - return this.AssertReply((reply) -> { - for (String candidate : candidates) { - if (reply.text() == candidate) - return null; - } - return String.format("%s: Not one of candidates: %s", description, String.join("\n ", candidates)); - }, description, timeout); - } - -} +package com.microsoft.bot.builder.adapters; + +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.connector.ExecutorFactory; +import com.microsoft.bot.schema.ActivityImpl; +import com.microsoft.bot.schema.models.Activity; +import org.joda.time.DateTime; +import org.junit.Assert; + +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.concurrent.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import static java.util.concurrent.CompletableFuture.completedFuture; + +public class TestFlow { + final TestAdapter adapter; + CompletableFuture testTask; + Consumer callback; + + ArrayList> tasks = new ArrayList>(); + ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() + { + @Override + public ForkJoinWorkerThread newThread(ForkJoinPool pool) + { + final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); + worker.setName("TestFlow-" + worker.getPoolIndex()); + return worker; + } + }; + + ExecutorService executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), factory, null, true); + + + public TestFlow(TestAdapter adapter) { + this(adapter, null); + } + + public TestFlow(TestAdapter adapter, Consumer callback) { + this.adapter = adapter; + this.callback = callback; + this.testTask = completedFuture(null); + } + + + public TestFlow(Supplier testTask, TestFlow flow) { + this.tasks = flow.tasks; + if (testTask != null) + this.tasks.add(testTask); + this.callback = flow.callback; + this.adapter = flow.adapter; + } + + + /** + * Start the execution of the test flow + * + * @return + */ + public String StartTest() throws ExecutionException, InterruptedException { + + System.out.printf("+------------------------------------------+\n"); + int count = 0; + for (Supplier task : this.tasks) { + System.out.printf("| Running task %s of %s\n", count++, this.tasks.size()); + String result = null; + result = task.get(); + System.out.printf("| --> Result: %s", result); + System.out.flush(); + } + System.out.printf("+------------------------------------------+\n"); + return "Completed"; + + } + + /** + * Send a message from the user to the bot + * + * @param userSays + * @return + */ + public TestFlow Send(String userSays) throws IllegalArgumentException { + if (userSays == null) + throw new IllegalArgumentException("You have to pass a userSays parameter"); + + // Function + return new TestFlow((() -> { + System.out.print(String.format("USER SAYS: %s (Thread Id: %s)\n", userSays, Thread.currentThread().getId())); + System.out.flush(); + try { + this.adapter.SendTextToBot(userSays, this.callback); + return "Successfully sent " + userSays; + } catch (Exception e) { + Assert.fail(e.getMessage()); + return e.getMessage(); + } + }), this); + } + + /** + * Send an activity from the user to the bot + * + * @param userActivity + * @return + */ + public TestFlow Send(Activity userActivity) { + if (userActivity == null) + throw new IllegalArgumentException("You have to pass an Activity"); + + return new TestFlow((() -> { + System.out.printf("TestFlow(%s): Send with User Activity! %s", Thread.currentThread().getId(), userActivity.text()); + System.out.flush(); + + + try { + this.adapter.ProcessActivity((ActivityImpl) userActivity, this.callback); + return "TestFlow: Send() -> ProcessActivity: " + userActivity.text(); + } catch (Exception e) { + return e.getMessage(); + + } + + }), this); + } + + /** + * Delay for time period + * + * @param ms + * @return + */ + public TestFlow Delay(int ms) { + return new TestFlow(() -> + { + System.out.printf("TestFlow(%s): Delay(%s ms) called. ", Thread.currentThread().getId(), ms); + System.out.flush(); + try { + Thread.sleep((int) ms); + } catch (InterruptedException e) { + return e.getMessage(); + } + return null; + }, this); + } + + /** + * Assert that reply is expected text + * + * @param expected + * @param description + * @param timeout + * @return + */ + public TestFlow AssertReply(String expected) { + return this.AssertReply(expected, null, 3000); + } + + public TestFlow AssertReply(String expected, String description) { + return this.AssertReply(expected, description, 3000); + } + + public TestFlow AssertReply(String expected, String description, int timeout) { + return this.AssertReply(this.adapter.MakeActivity(expected), description, timeout); + } + + /** + * Assert that the reply is expected activity + * + * @param expected + * @param description + * @param timeout + * @return + */ + public TestFlow AssertReply(Activity expected) { + String description = Thread.currentThread().getStackTrace()[1].getMethodName(); + return AssertReply(expected, description, 3000); + } + + public TestFlow AssertReply(Activity expected, String description, int timeout) { + if (description == null) + description = Thread.currentThread().getStackTrace()[1].getMethodName(); + String finalDescription = description; + return this.AssertReply((reply) -> { + if (expected.type() != reply.type()) + return String.format("%s: Type should match", finalDescription); + if (expected.text().equals(reply.text())) { + if (finalDescription == null) + return String.format("Expected:%s\nReceived:{reply.AsMessageActivity().Text}", expected.text()); + else + return String.format("%s: Text should match", finalDescription); + } + // TODO, expand this to do all properties set on expected + return null; + }, description, timeout); + } + + /** + * Assert that the reply matches a custom validation routine + * + * @param validateActivity + * @param description + * @param timeout + * @return + */ + public TestFlow AssertReply(Function validateActivity) { + String description = Thread.currentThread().getStackTrace()[1].getMethodName(); + return AssertReply(validateActivity, description, 3000); + } + + public TestFlow AssertReply(Function validateActivity, String description) { + return AssertReply(validateActivity, description, 3000); + } + + public TestFlow AssertReply(Function validateActivity, String description, int timeout) { + return new TestFlow(() -> { + System.out.println(String.format("AssertReply: Starting loop : %s (Thread:%s)", description, Thread.currentThread().getId())); + System.out.flush(); + + int finalTimeout = Integer.MAX_VALUE; + if (isDebug()) + finalTimeout = Integer.MAX_VALUE; + + DateTime start = DateTime.now(); + while (true) { + DateTime current = DateTime.now(); + + if ((current.getMillis() - start.getMillis()) > (long) finalTimeout) { + System.out.println("AssertReply: Timeout!\n"); + System.out.flush(); + return String.format("%d ms Timed out waiting for:'%s'", finalTimeout, description); + } + +// System.out.println("Before GetNextReply\n"); +// System.out.flush(); + + Activity replyActivity = this.adapter.GetNextReply(); +// System.out.println("After GetNextReply\n"); +// System.out.flush(); + + if (replyActivity != null) { + System.out.printf("AssertReply(tid:%s): Received Reply: %s ", Thread.currentThread().getId(), (replyActivity.text() == null) ? "No Text set" : replyActivity.text()); + System.out.flush(); + System.out.printf("=============\n From: %s\n To:%s\n ==========\n", (replyActivity.from() == null) ? "No from set" : replyActivity.from().name(), + (replyActivity.recipient() == null) ? "No recipient set" : replyActivity.recipient().name()); + System.out.flush(); + + // if we have a reply + return validateActivity.apply(replyActivity); + } else { + System.out.printf("AssertReply(tid:%s): Waiting..\n", Thread.currentThread().getId()); + System.out.flush(); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }, this); + } + + // Hack to determine if debugger attached.. + public boolean isDebug() { + for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) { + if (arg.contains("jdwp=")) { + return true; + } + } + return false; + } + + + /** + * @param userSays + * @param expected + * @return + */ + public TestFlow Turn(String userSays, String expected, String description, int timeout) { + String result = null; + try { + + result = CompletableFuture.supplyAsync(() -> { // Send the message + + if (userSays == null) + throw new IllegalArgumentException("You have to pass a userSays parameter"); + + System.out.print(String.format("TestTurn(%s): USER SAYS: %s \n", Thread.currentThread().getId(), userSays)); + System.out.flush(); + + try { + this.adapter.SendTextToBot(userSays, this.callback); + return null; + } catch (Exception e) { + return e.getMessage(); + } + + }, ExecutorFactory.getExecutor()) + .thenApply(arg -> { // Assert Reply + int finalTimeout = Integer.MAX_VALUE; + if (isDebug()) + finalTimeout = Integer.MAX_VALUE; + Function validateActivity = activity -> { + if (activity.text().equals(expected)) { + System.out.println(String.format("TestTurn(tid:%s): Validated text is: %s", Thread.currentThread().getId(), expected)); + System.out.flush(); + + return "SUCCESS"; + } + System.out.println(String.format("TestTurn(tid:%s): Failed validate text is: %s", Thread.currentThread().getId(), expected)); + System.out.flush(); + + return String.format("FAIL: %s received in Activity.text (%s expected)", activity.text(), expected); + }; + + + System.out.println(String.format("TestTurn(tid:%s): Started receive loop: %s", Thread.currentThread().getId(), description)); + System.out.flush(); + DateTime start = DateTime.now(); + while (true) { + DateTime current = DateTime.now(); + + if ((current.getMillis() - start.getMillis()) > (long) finalTimeout) + return String.format("TestTurn: %d ms Timed out waiting for:'%s'", finalTimeout, description); + + + Activity replyActivity = this.adapter.GetNextReply(); + + + if (replyActivity != null) { + // if we have a reply + System.out.println(String.format("TestTurn(tid:%s): Received Reply: %s", + Thread.currentThread().getId(), + String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.recipient().name(), replyActivity.from().name(), replyActivity.text()) + )); + System.out.flush(); + return validateActivity.apply(replyActivity); + } else { + System.out.println(String.format("TestTurn(tid:%s): No reply..", Thread.currentThread().getId())); + System.out.flush(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + }) + .get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); + } + return this; + + } + + /** + * Say() -> shortcut for .Send(user).AssertReply(Expected) + * + * @param userSays + * @param expected + * @param description + * @param timeout + * @return + */ + public TestFlow Test(String userSays, String expected) { + return Test(userSays, expected, null, 3000); + } + + public TestFlow Test(String userSays, String expected, String description) { + return Test(userSays, expected, description, 3000); + } + + public TestFlow Test(String userSays, String expected, String description, int timeout) { + if (expected == null) + throw new IllegalArgumentException("expected"); + + return this.Send(userSays) + .AssertReply(expected, description, timeout); + } + + /** + * Test() -> shortcut for .Send(user).AssertReply(Expected) + * + * @param userSays + * @param expected + * @param description + * @param timeout + * @return + */ + public TestFlow Test(String userSays, Activity expected) { + return Test(userSays, expected, null, 3000); + } + + public TestFlow Test(String userSays, Activity expected, String description) { + return Test(userSays, expected, description, 3000); + } + + public TestFlow Test(String userSays, Activity expected, String description, int timeout) { + if (expected == null) + throw new IllegalArgumentException("expected"); + + return this.Send(userSays) + .AssertReply(expected, description, timeout); + } + + /** + * Say() -> shortcut for .Send(user).AssertReply(Expected) + * + * @param userSays + * @param expected + * @param description + * @param timeout + * @return + */ + public TestFlow Test(String userSays, Function expected) { + return Test(userSays, expected, null, 3000); + } + + public TestFlow Test(String userSays, Function expected, String description) { + return Test(userSays, expected, description, 3000); + } + + public TestFlow Test(String userSays, Function expected, String description, int timeout) { + if (expected == null) + throw new IllegalArgumentException("expected"); + + return this.Send(userSays) + .AssertReply(expected, description, timeout); + } + + /** + * Assert that reply is one of the candidate responses + * + * @param candidates + * @param description + * @param timeout + * @return + */ + public TestFlow AssertReplyOneOf(String[] candidates) { + return AssertReplyOneOf(candidates, null, 3000); + } + + public TestFlow AssertReplyOneOf(String[] candidates, String description) { + return AssertReplyOneOf(candidates, description, 3000); + } + + public TestFlow AssertReplyOneOf(String[] candidates, String description, int timeout) { + if (candidates == null) + throw new IllegalArgumentException("candidates"); + + return this.AssertReply((reply) -> { + for (String candidate : candidates) { + if (reply.text() == candidate) + return null; + } + return String.format("%s: Not one of candidates: %s", description, String.join("\n ", candidates)); + }, description, timeout); + } + +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index 2cb597bb8..b26682f7c 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -4,6 +4,7 @@ package com.microsoft.bot.connector.authentication; import com.microsoft.aad.adal4j.AuthenticationException; +import com.microsoft.bot.connector.ExecutorFactory; import org.apache.commons.lang3.StringUtils; import java.time.Duration; @@ -113,6 +114,6 @@ public static CompletableFuture validateIdentity(ClaimsIdentity } return identity; - }); + }, ExecutorFactory.getExecutor()); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java index 76bef99e7..41fda19c2 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java @@ -9,6 +9,7 @@ import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.Verification; import com.microsoft.aad.adal4j.AuthenticationException; +import com.microsoft.bot.connector.ExecutorFactory; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -113,6 +114,6 @@ private CompletableFuture validateTokenAsync(String token, Strin LOGGER.warn(errorDescription); throw new AuthenticationException(ex); } - }); + }, ExecutorFactory.getExecutor()); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 5fb679a8e..0c4a10546 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -4,6 +4,7 @@ package com.microsoft.bot.connector.authentication; import com.microsoft.aad.adal4j.AuthenticationException; +import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.schema.models.Activity; import org.apache.commons.lang3.StringUtils; @@ -62,7 +63,7 @@ public static CompletableFuture authenticateRequest(Activity act MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); return identity; - }); + }, ExecutorFactory.getExecutor()); } /** diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java index d37d2ac72..3dd10eb28 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.UserAgent; import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.schema.TokenExchangeState; @@ -161,7 +162,7 @@ public CompletableFuture GetUserTokenAsync(String userId, String response.body().close(); } return null; - }); + }, ExecutorFactory.getExecutor()); } /** @@ -221,7 +222,7 @@ public CompletableFuture SignOutUserAsync(String userId, String connect } return false; - }); + }, ExecutorFactory.getExecutor()); } @@ -287,7 +288,7 @@ public CompletableFuture GetSignInLinkAsync(Activity activity, String co e.printStackTrace(); } return null; - }); + }, ExecutorFactory.getExecutor()); } /** @@ -339,6 +340,6 @@ public CompletableFuture SendEmulateOAuthCardsAsync(Boolean emulateOAuthCards) t // Apparently swallow any results return; - }); + }, ExecutorFactory.getExecutor()); } } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java index 1aaa5a68d..615d3d2f8 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java @@ -118,7 +118,7 @@ public CompletableFuture UseOAuthClientFor(Function incoming(@RequestBody Activity activity, new Activity().withType(ActivityTypes.MESSAGE).withText("Echo: " + activity.text()) .withRecipient(activity.from()).withFrom(activity.recipient())); } - }).join(); + }, ExecutorFactory.getExecutor()).join(); } catch (CompletionException ex) { if (ex.getCause() instanceof AuthenticationException) { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); From 9956b97364824b76f7b2b184d6a830de64f44ca7 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 13:30:18 -0500 Subject: [PATCH 13/26] Added missing JwtTokenValidationTests and corrected some goofy CompletableFuture impls. --- .../authentication/ChannelValidation.java | 16 +- .../authentication/EmulatorValidation.java | 2 +- .../authentication/EndorsementsValidator.java | 4 +- .../EnterpriseChannelValidation.java | 14 +- .../GovernmentChannelValidation.java | 64 ++-- .../authentication/JwtTokenExtractor.java | 2 +- .../connector/JwtTokenValidationTests.java | 294 ++++++++++++++---- 7 files changed, 289 insertions(+), 107 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index e5ae4adac..8064cec5b 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -66,23 +66,19 @@ public static CompletableFuture authenticateToken(String authHea // Look for the "aud" claim, but only if issued from the Bot Framework if (!identity.getIssuer().equalsIgnoreCase(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER)) { - throw new AuthenticationException("Token Not Authenticated"); + throw new AuthenticationException("Wrong Issuer"); } - return identity; - }) - - .thenApply(identity -> { // The AppId from the claim in the token must match the AppId specified by the developer. Note that // the Bot Framework uses the Audience claim ("aud") to pass the AppID. - String appIdFromClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); - if (StringUtils.isEmpty(appIdFromClaim)) { + String appIdFromAudienceClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromAudienceClaim)) { // Claim is present, but doesn't have a value. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); + throw new AuthenticationException("No Audience Claim"); } - if (!credentials.isValidAppIdAsync(appIdFromClaim).join()) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); + if (!credentials.isValidAppIdAsync(appIdFromAudienceClaim).join()) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); } return identity; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index 673ee9c44..93ad9f9d5 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -147,7 +147,7 @@ public static CompletableFuture authenticateToken(String authHea // The Emulator, depending on Version, sends the AppId via either the // appid claim (Version 1) or the Authorized Party claim (Version 2). - if (tokenVersion.isEmpty() || tokenVersion.equalsIgnoreCase("1.0")) { + if (StringUtils.isEmpty(tokenVersion) || tokenVersion.equalsIgnoreCase("1.0")) { // either no Version or a version of "1.0" means we should look for // the claim in the "appid" claim. if (!identity.claims().containsKey(AuthenticationConstants.APPID_CLAIM)) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java index 1ed646059..f1b6b0288 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java @@ -3,6 +3,8 @@ package com.microsoft.bot.connector.authentication; +import org.apache.commons.lang3.StringUtils; + import java.util.List; public abstract class EndorsementsValidator { @@ -22,7 +24,7 @@ public static boolean validate(String channelId, List endorsements) { // If the Activity came in and doesn't have a Channel ID then it's making no // assertions as to who endorses it. This means it should pass. - if (channelId == null || channelId.isEmpty()) + if (StringUtils.isEmpty(channelId)) return true; if (endorsements == null) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index b26682f7c..265401525 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -91,17 +91,21 @@ public static CompletableFuture validateIdentity(ClaimsIdentity // comes from developer code that may be reaching out to a service, hence the // Async validation. + if (!StringUtils.equalsIgnoreCase(identity.getIssuer(), AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER)) { + throw new AuthenticationException("Wrong Issuer"); + } + // The AppId from the claim in the token must match the AppId specified by the developer. Note that // the Bot Framework uses the Audience claim ("aud") to pass the AppID. - String appIdFromClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); - if (StringUtils.isEmpty(appIdFromClaim)) { + String appIdFromAudienceClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromAudienceClaim)) { // Claim is present, but doesn't have a value. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); + throw new AuthenticationException("No Audience Claim"); } - boolean isValid = credentials.isValidAppIdAsync(appIdFromClaim).join(); + boolean isValid = credentials.isValidAppIdAsync(appIdFromAudienceClaim).join(); if (!isValid) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); } String serviceUrlClaim = identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java index c10d52b10..af5494e48 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java @@ -85,38 +85,38 @@ public static CompletableFuture validateIdentity(ClaimsIdentity throw new AuthenticationException("Invalid Identity"); } + // Now check that the AppID in the claim set matches + // what we're looking for. Note that in a multi-tenant bot, this value + // comes from developer code that may be reaching out to a service, hence the + // Async validation. + + if (!StringUtils.equalsIgnoreCase(identity.getIssuer(), GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER)) { + throw new AuthenticationException("Wrong Issuer"); + } + + // The AppId from the claim in the token must match the AppId specified by the developer. Note that + // the Bot Framework uses the Audience claim ("aud") to pass the AppID. + String appIdFromAudienceClaim = identity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); + if (StringUtils.isEmpty(appIdFromAudienceClaim)) { + // Claim is present, but doesn't have a value. Not Authorized. + throw new AuthenticationException("No Audience Claim"); + } + + boolean isValid = credentials.isValidAppIdAsync(appIdFromAudienceClaim).join(); + if (!isValid) { + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); + } + + String serviceUrlClaim = identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); + if (StringUtils.isEmpty(serviceUrl)) { + throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); + } + + if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { + throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); + } + return identity; - }, ExecutorFactory.getExecutor()) - - .thenApply(theIdentity -> { - // Now check that the AppID in the claim set matches - // what we're looking for. Note that in a multi-tenant bot, this value - // comes from developer code that may be reaching out to a service, hence the - // Async validation. - - // The AppId from the claim in the token must match the AppId specified by the developer. Note that - // the Bot Framework uses the Audience claim ("aud") to pass the AppID. - String appIdFromClaim = theIdentity.claims().get(AuthenticationConstants.AUDIENCE_CLAIM); - if (StringUtils.isEmpty(appIdFromClaim)) { - // Claim is present, but doesn't have a value. Not Authorized. - throw new AuthenticationException("Token Not Authenticated"); - } - - boolean isValid = credentials.isValidAppIdAsync(appIdFromClaim).join(); - if (!isValid) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromClaim)); - } - - String serviceUrlClaim = theIdentity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); - if (StringUtils.isEmpty(serviceUrl)) { - throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); - } - - if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { - throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); - } - - return theIdentity; - }); + }, ExecutorFactory.getExecutor()); } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java index 41fda19c2..b37b905ba 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java @@ -42,7 +42,7 @@ public CompletableFuture getIdentityAsync(String authorizationHe public CompletableFuture getIdentityAsync(String authorizationHeader, String channelId, List requiredEndorsements) { if (authorizationHeader == null) { - return CompletableFuture.completedFuture(null); + throw new IllegalArgumentException("authorizationHeader is required"); } String[] parts = authorizationHeader.split(" "); diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index b50d0007c..419e07301 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -6,12 +6,10 @@ import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.schema.models.Activity; -import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; import java.io.IOException; -import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletionException; @@ -66,7 +64,7 @@ public void ConnectorAuthHeaderBotAppIdDiffersShouldNotValidate() throws IOExcep "", null).join(); } catch (CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -84,7 +82,7 @@ public void ConnectorAuthHeaderBotWithNoCredentialsShouldNotValidate() throws IO "", null).join(); } catch (CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -133,7 +131,7 @@ public void EmulatorMsaHeaderBotAppIdDiffersShouldNotValidate() throws IOExcepti "", null).join(); } catch (CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -185,7 +183,7 @@ public void ChannelMsaHeaderInvalidServiceUrlShouldNotBeTrusted() throws IOExcep new SimpleChannelProvider()).join(); Assert.fail("Should have thrown AuthenticationException"); } catch (CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + Assert.assertTrue(e.getCause() instanceof AuthenticationException); Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://webchat.botframework.com/")); } } @@ -217,8 +215,8 @@ public void ChannelNoHeaderAuthenticationEnabledShouldThrow() throws IOException credentials, new SimpleChannelProvider()).join(); Assert.fail("Should have thrown AuthenticationException"); - } catch(CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } Assert.assertFalse(MicrosoftAppCredentials.isTrustedServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/")); @@ -246,14 +244,15 @@ public void EnterpriseChannelValidation_Succeeds() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, null); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); try { EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); - } catch (Exception e) { + } catch (CompletionException e) { Assert.fail("Should not have thrown " + e.getCause().getClass().getName()); } } @@ -264,16 +263,17 @@ public void EnterpriseChannelValidation_NoAuthentication_Fails() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, null); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; ClaimsIdentity identity = new ClaimsIdentity(null, claims); try { EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an AuthenticationException"); - } catch (Exception e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -283,15 +283,36 @@ public void EnterpriseChannelValidation_NoAudienceClaim_Fails() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, null); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); try { EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an AuthenticationException"); - } catch (Exception e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void EnterpriseChannelValidation_NoAudienceClaimValue_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, ""); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -301,16 +322,76 @@ public void EnterpriseChannelValidation_WrongAudienceClaim_Fails() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, null); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); try { EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an AuthenticationException"); - } catch (Exception e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void EnterpriseChannelValidation_NoServiceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void EnterpriseChannelValidation_NoServiceClaimValue_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, ""); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void EnterpriseChannelValidation_WrongServiceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, null); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, "other"); + }}; + ClaimsIdentity identity = new ClaimsIdentity(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + EnterpriseChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an AuthenticationException"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -320,16 +401,16 @@ public void GovernmentChannelValidation_Succeeds() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity("anonymous", claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); try { GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); - Assert.assertTrue(true); - } catch(Exception e) { - Assert.fail("Should not have thrown " + e.getCause().getClass().getName()); + } catch (Exception e) { + Assert.fail("Should not have thrown " + e.getCause().getClass().getName() + ": " + e.getCause().getMessage()); } } @@ -339,16 +420,56 @@ public void GovernmentChannelValidation_NoAuthentication_Fails() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; ClaimsIdentity identity = new ClaimsIdentity(null, claims); try { GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an Authorization exception"); - } catch(CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void GovernmentChannelValidation_NoAudienceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void GovernmentChannelValidation_NoAudienceClaimValue_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, ""); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } @@ -358,43 +479,102 @@ public void GovernmentChannelValidation_WrongAudienceClaim_Fails() { String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity(null, claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, "abc"); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); try { GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an Authorization exception"); - } catch(CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } - /* @Test public void GovernmentChannelValidation_WrongAudienceClaimIssuer_Fails() { String appId = "1234567890"; String serviceUrl = "https://webchat.botframework.com/"; CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); - Map claims = new HashMap<>(); - claims.put(AuthenticationConstants.AUDIENCE_CLAIM, appId); - claims.put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); - ClaimsIdentity identity = new ClaimsIdentity(null, claims); + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl); + }}; + ClaimsIdentity identity = new ClaimsIdentity("https://wrongissuer.com", claims); try { GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); Assert.fail("Should have thrown an Authorization exception"); - } catch(CompletionException e) { - Assert.assertTrue(StringUtils.equals(e.getCause().getClass().getName(), AuthenticationException.class.getName())); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void GovernmentChannelValidation_NoServiceClaim_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void GovernmentChannelValidation_NoServiceClaimValue_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, ""); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); + } + } + + @Test + public void GovernmentChannelValidation_WrongServiceClaimValue_Fails() { + String appId = "1234567890"; + String serviceUrl = "https://webchat.botframework.com/"; + CredentialProvider credentials = new SimpleCredentialProvider(appId, ""); + + Map claims = new HashMap() {{ + put(AuthenticationConstants.AUDIENCE_CLAIM, appId); + put(AuthenticationConstants.SERVICE_URL_CLAIM, "other"); + }}; + ClaimsIdentity identity = new ClaimsIdentity(GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER, claims); + + try { + GovernmentChannelValidation.validateIdentity(identity, credentials, serviceUrl).join(); + Assert.fail("Should have thrown an Authorization exception"); + } catch (CompletionException e) { + Assert.assertTrue(e.getCause() instanceof AuthenticationException); } } - */ private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(String appId, String pwd, String channelService) throws IOException, ExecutionException, InterruptedException { ChannelProvider channel = new SimpleChannelProvider(channelService); - String header = channel.isGovernment()?getGovHeaderToken():getHeaderToken(); + String header = channel.isGovernment() ? getGovHeaderToken() : getHeaderToken(); JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(header, appId, pwd, channel); } @@ -411,7 +591,7 @@ private void JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(S "https://webchat.botframework.com/").join(); Assert.assertTrue(identity.isAuthenticated()); - } catch(Exception e) { + } catch (Exception e) { Assert.fail("Should not have thrown " + e.getClass().getName()); } } From fc8efe06de044178e4c83f7f94d5873e98adf177 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 15:14:03 -0500 Subject: [PATCH 14/26] Update to latest json and auth0 dependencies --- libraries/bot-connector/pom.xml | 4 ++++ .../authentication/ChannelValidation.java | 13 ++++++++++++- .../TokenValidationParameters.java | 14 -------------- pom.xml | 17 +++++++++++------ 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/libraries/bot-connector/pom.xml b/libraries/bot-connector/pom.xml index 00832d30e..b88c170e0 100644 --- a/libraries/bot-connector/pom.xml +++ b/libraries/bot-connector/pom.xml @@ -86,6 +86,10 @@ com.auth0 jwks-rsa + + commons-io + commons-io + com.microsoft.bot diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index 8064cec5b..5e17c8d95 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -6,13 +6,24 @@ import com.microsoft.aad.adal4j.AuthenticationException; import org.apache.commons.lang3.StringUtils; +import java.time.Duration; +import java.util.ArrayList; import java.util.concurrent.CompletableFuture; public class ChannelValidation { /** * TO BOT FROM CHANNEL: Token validation parameters when connecting to a bot */ - public static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = TokenValidationParameters.toBotFromChannelTokenValidationParameters(); + public static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ + this.validateIssuer = true; + this.validIssuers = new ArrayList() {{ + add(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); + }}; + this.validateAudience = false; + this.validateLifetime = true; + this.clockSkew = Duration.ofMinutes(5); + this.requireSignedTokens = true; + }}; /** * Validate the incoming Auth Header as a token sent from the Bot Framework Service. diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java index 530eb4c76..98b90ef2f 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java @@ -4,7 +4,6 @@ package com.microsoft.bot.connector.authentication; import java.time.Duration; -import java.util.ArrayList; import java.util.List; public class TokenValidationParameters { @@ -30,17 +29,4 @@ public TokenValidationParameters(boolean validateIssuer, List validIssue this.clockSkew = clockSkew; this.requireSignedTokens = requireSignedTokens; } - - static TokenValidationParameters toBotFromChannelTokenValidationParameters() { - return new TokenValidationParameters() {{ - this.validateIssuer = true; - this.validIssuers = new ArrayList() {{ - add(AuthenticationConstants.TO_BOT_FROM_CHANNEL_TOKEN_ISSUER); - }}; - this.validateAudience = false; - this.validateLifetime = true; - this.clockSkew = Duration.ofMinutes(5); - this.requireSignedTokens = true; - }}; - } } diff --git a/pom.xml b/pom.xml index 9e5cb3a2b..1e0957d8f 100644 --- a/pom.xml +++ b/pom.xml @@ -66,27 +66,27 @@ com.fasterxml.jackson.module jackson-module-parameter-names - 2.9.8 + 2.9.9 com.fasterxml.jackson.datatype jackson-datatype-jdk8 - 2.9.8 + 2.9.9 com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.9.8 + 2.9.9 com.auth0 java-jwt - 3.3.0 + 3.8.2 com.auth0 jwks-rsa - 0.3.0 + 0.8.3 org.slf4j @@ -101,7 +101,12 @@ org.apache.commons commons-lang3 - 3.4 + 3.9 + + + commons-io + commons-io + 2.6 From 32960b9f8df1d4bb4a5cc52ed00cd6426ddcfa42 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Thu, 22 Aug 2019 15:27:27 -0500 Subject: [PATCH 15/26] Switched to using our own checkstyle file. --- etc/bot-checkstyle.xml | 179 +++++++++++++++++++++++++++++++++++++++++ pom.xml | 2 +- 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 etc/bot-checkstyle.xml diff --git a/etc/bot-checkstyle.xml b/etc/bot-checkstyle.xml new file mode 100644 index 000000000..55fa68e98 --- /dev/null +++ b/etc/bot-checkstyle.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 1e0957d8f..b838a9558 100644 --- a/pom.xml +++ b/pom.xml @@ -189,7 +189,7 @@ maven-checkstyle-plugin ${checkstyle.version} - + ./etc/bot-checkstyle.xml UTF-8 false false From 1cbe46b81c7e612b24952000af9827e362b12a66 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Mon, 26 Aug 2019 21:04:11 -0500 Subject: [PATCH 16/26] bot-schema recfactor (periodic push) --- etc/bot-checkstyle.xml | 7 +- .../com/microsoft/bot/builder/BotAdapter.java | 348 +++-- .../com/microsoft/bot/builder/BotAssert.java | 186 ++- .../bot/builder/BotFrameworkAdapter.java | 85 +- .../bot/builder/ConversationState.java | 98 +- .../bot/builder/DeleteActivityHandler.java | 50 +- .../bot/builder/MemoryTranscriptStore.java | 35 +- .../bot/builder/SendActivitiesHandler.java | 25 +- .../bot/builder/TraceTranscriptLogger.java | 103 +- .../bot/builder/TranscriptLogger.java | 42 +- .../builder/TranscriptLoggerMiddleware.java | 381 +++--- .../bot/builder/TranscriptStore.java | 114 +- .../microsoft/bot/builder/TurnContext.java | 396 +++--- .../bot/builder/TurnContextImpl.java | 125 +- .../bot/builder/UpdateActivityHandler.java | 58 +- .../com/microsoft/bot/builder/UserState.java | 100 +- .../bot/builder/adapters/TestAdapter.java | 471 +++---- .../bot/builder/dialogs/MessageOptions.java | 114 +- .../InspectionActivityExtensions.java | 4 + .../microsoft/bot/builder/prompts/Choice.java | 86 +- .../bot/builder/BotFrameworkAdapterTest.java | 86 +- .../microsoft/bot/builder/BotStateTest.java | 31 +- .../CatchException_MiddlewareTest.java | 13 +- .../bot/builder/MiddlewareSetTest.java | 6 +- .../microsoft/bot/builder/SimpleAdapter.java | 173 ++- .../microsoft/bot/builder/TestMessage.java | 61 +- .../bot/builder/TranscriptMiddlewareTest.java | 526 ++++---- .../bot/builder/adapters/TestFlow.java | 44 +- .../microsoft/bot/connector/Attachments.java | 2 +- .../bot/connector/Conversations.java | 2 +- .../authentication/JwtTokenValidation.java | 6 +- .../connector/authentication/OAuthClient.java | 28 +- .../rest/ErrorResponseException.java | 2 +- .../bot/connector/rest/RestAttachments.java | 2 +- .../bot/connector/rest/RestConversations.java | 10 +- .../bot/connector/AttachmentsTest.java | 50 +- .../bot/connector/BotConnectorTestBase.java | 6 +- .../bot/connector/ConversationsTest.java | 514 +++---- .../connector/JwtTokenValidationTests.java | 22 +- .../bot/connector/OAuthTestBase.java | 28 +- .../bot/schema/{models => }/ActionTypes.java | 189 +-- .../com/microsoft/bot/schema/Activity.java | 1191 +++++++++++++++++ .../microsoft/bot/schema/ActivityImpl.java | 782 ----------- .../{models => }/ActivityImportance.java | 125 +- .../schema/{models => }/ActivityTypes.java | 221 +-- .../schema/{models => }/AnimationCard.java | 636 +++++---- .../bot/schema/{models => }/Attachment.java | 354 +++-- .../schema/{models => }/AttachmentData.java | 234 ++-- .../schema/{models => }/AttachmentInfo.java | 186 ++- .../{models => }/AttachmentLayoutTypes.java | 117 +- .../schema/{models => }/AttachmentView.java | 133 +- .../bot/schema/{models => }/AudioCard.java | 637 +++++---- .../bot/schema/{models => }/BasicCard.java | 336 +++-- .../bot/schema/{models => }/CardAction.java | 385 +++--- .../bot/schema/{models => }/CardImage.java | 183 ++- .../microsoft/bot/schema/ChannelAccount.java | 190 +++ .../ContactRelationUpdateActionTypes.java | 117 +- .../schema/ContactRelationUpdateActivity.java | 18 - .../bot/schema/ConversationAccount.java | 253 ++++ .../bot/schema/ConversationMembers.java | 60 + .../bot/schema/ConversationParameters.java | 171 +++ .../{models => }/ConversationReference.java | 335 +++-- .../schema/ConversationReferenceHelper.java | 55 + .../ConversationResourceResponse.java | 185 ++- .../{models => }/ConversationsResult.java | 136 +- .../schema/{models => }/DeliveryModes.java | 119 +- .../{models => }/EndOfConversationCodes.java | 149 ++- .../schema/{EntityImpl.java => Entity.java} | 278 ++-- .../bot/schema/EntitySerialization.java | 10 + .../bot/schema/{models => }/Error.java | 173 ++- .../schema/{models => }/ErrorResponse.java | 91 +- .../bot/schema/{models => }/Fact.java | 139 +- .../schema/{models => }/GeoCoordinates.java | 281 ++-- .../bot/schema/{models => }/HeroCard.java | 336 +++-- .../schema/{models => }/InnerHttpError.java | 124 +- .../bot/schema/{models => }/InputHints.java | 125 +- .../InstallationUpdateActionTypes.java | 117 +- .../bot/schema/{models => }/MediaCard.java | 636 +++++---- .../schema/{models => }/MediaEventValue.java | 89 +- .../bot/schema/{models => }/MediaUrl.java | 135 +- .../bot/schema/{models => }/Mention.java | 176 ++- .../schema/{models => }/MessageReaction.java | 83 +- .../{models => }/MessageReactionTypes.java | 117 +- .../{models => }/MicrosoftPayMethodData.java | 187 ++- .../bot/schema/{models => }/OAuthCard.java | 186 ++- .../{models => }/PagedMembersResult.java | 124 +- .../schema/{models => }/PaymentAddress.java | 605 ++++----- .../{models => }/PaymentCurrencyAmount.java | 183 ++- .../schema/{models => }/PaymentDetails.java | 290 ++-- .../{models => }/PaymentDetailsModifier.java | 246 ++-- .../bot/schema/{models => }/PaymentItem.java | 183 ++- .../{models => }/PaymentMethodData.java | 142 +- .../schema/{models => }/PaymentOptions.java | 295 ++-- .../schema/{models => }/PaymentRequest.java | 286 ++-- .../{models => }/PaymentRequestComplete.java | 183 ++- .../PaymentRequestCompleteResult.java | 83 +- .../{models => }/PaymentRequestUpdate.java | 233 ++-- .../PaymentRequestUpdateResult.java | 83 +- .../schema/{models => }/PaymentResponse.java | 358 +++-- .../{models => }/PaymentShippingOption.java | 233 ++-- .../bot/schema/{models => }/Place.java | 282 ++-- .../bot/schema/{models => }/ReceiptCard.java | 438 +++--- .../bot/schema/{models => }/ReceiptItem.java | 387 +++--- .../schema/{models => }/ResourceResponse.java | 91 +- .../com/microsoft/bot/schema/ResultPair.java | 27 +- .../bot/schema/{models => }/RoleTypes.java | 117 +- .../schema/{models => }/SemanticAction.java | 131 +- .../{models => }/SemanticActionStates.java | 127 +- .../bot/schema/{models => }/SigninCard.java | 136 +- .../schema/{models => }/SuggestedActions.java | 140 +- .../schema/{models => }/TextFormatTypes.java | 125 +- .../schema/{models => }/TextHighlight.java | 133 +- .../bot/schema/{models => }/Thing.java | 133 +- .../schema/{models => }/ThumbnailCard.java | 336 +++-- .../bot/schema/{models => }/ThumbnailUrl.java | 133 +- .../bot/schema/TokenExchangeState.java | 132 +- .../bot/schema/{models => }/TokenRequest.java | 136 +- .../schema/{models => }/TokenResponse.java | 229 ++-- .../microsoft/bot/schema/TraceActivity.java | 73 - .../bot/schema/{models => }/Transcript.java | 85 +- .../bot/schema/{models => }/VideoCard.java | 637 +++++---- .../microsoft/bot/schema/models/Activity.java | 1178 ---------------- .../bot/schema/models/ChannelAccount.java | 156 --- .../schema/models/ConversationAccount.java | 231 ---- .../schema/models/ConversationMembers.java | 72 - .../schema/models/ConversationParameters.java | 197 --- .../models/ConversationReferenceHelper.java | 50 - .../models/ConversationUpdateActivity.java | 64 - .../microsoft/bot/schema/models/Entity.java | 45 - .../bot/schema/models/MessageActivity.java | 190 --- .../bot/schema/{models => }/package-info.java | 50 +- .../microsoft/bot/schema/ActivityTest.java | 21 + .../schema/EntitySchemaValidationTest.java | 62 + libraries/swagger/generateClient.cmd | 2 +- .../microsoft/bot/connector/sample/App.java | 19 +- .../bot/sample/servlet/EchoServlet.java | 18 +- .../bot/sample/spring/BotController.java | 16 +- 137 files changed, 11790 insertions(+), 13356 deletions(-) create mode 100644 libraries/bot-builder/src/main/java/com/microsoft/bot/builder/inspection/InspectionActivityExtensions.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ActionTypes.java (59%) create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImpl.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ActivityImportance.java (67%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ActivityTypes.java (57%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AnimationCard.java (54%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Attachment.java (65%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AttachmentData.java (53%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AttachmentInfo.java (54%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AttachmentLayoutTypes.java (68%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AttachmentView.java (54%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/AudioCard.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/BasicCard.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/CardAction.java (58%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/CardImage.java (56%) create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ContactRelationUpdateActionTypes.java (68%) delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActivity.java create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationMembers.java create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationParameters.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ConversationReference.java (53%) create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReferenceHelper.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ConversationResourceResponse.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ConversationsResult.java (52%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/DeliveryModes.java (68%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/EndOfConversationCodes.java (64%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{EntityImpl.java => Entity.java} (57%) create mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntitySerialization.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Error.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ErrorResponse.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Fact.java (61%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/GeoCoordinates.java (53%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/HeroCard.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/InnerHttpError.java (57%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/InputHints.java (66%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/InstallationUpdateActionTypes.java (69%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MediaCard.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MediaEventValue.java (58%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MediaUrl.java (57%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Mention.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MessageReaction.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MessageReactionTypes.java (68%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/MicrosoftPayMethodData.java (58%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/OAuthCard.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PagedMembersResult.java (52%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentAddress.java (60%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentCurrencyAmount.java (52%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentDetails.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentDetailsModifier.java (58%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentItem.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentMethodData.java (60%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentOptions.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentRequest.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentRequestComplete.java (53%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentRequestCompleteResult.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentRequestUpdate.java (52%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentRequestUpdateResult.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentResponse.java (62%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/PaymentShippingOption.java (53%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Place.java (57%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ReceiptCard.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ReceiptItem.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ResourceResponse.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/RoleTypes.java (68%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/SemanticAction.java (54%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/SemanticActionStates.java (67%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/SigninCard.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/SuggestedActions.java (58%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/TextFormatTypes.java (67%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/TextHighlight.java (57%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Thing.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ThumbnailCard.java (55%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/ThumbnailUrl.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/TokenRequest.java (56%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/TokenResponse.java (54%) delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TraceActivity.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/Transcript.java (60%) rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/VideoCard.java (55%) delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Activity.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ChannelAccount.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationAccount.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationMembers.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationParameters.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReferenceHelper.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationUpdateActivity.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Entity.java delete mode 100644 libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageActivity.java rename libraries/bot-schema/src/main/java/com/microsoft/bot/schema/{models => }/package-info.java (50%) create mode 100644 libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java create mode 100644 libraries/bot-schema/src/test/java/com/microsoft/bot/schema/EntitySchemaValidationTest.java diff --git a/etc/bot-checkstyle.xml b/etc/bot-checkstyle.xml index 55fa68e98..3215799bd 100644 --- a/etc/bot-checkstyle.xml +++ b/etc/bot-checkstyle.xml @@ -53,7 +53,7 @@ - + @@ -83,7 +83,10 @@ + + + @@ -170,7 +173,7 @@ - + diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java index ed944c156..44d8a1f67 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAdapter.java @@ -1,176 +1,172 @@ -package com.microsoft.bot.builder; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.ConversationReferenceHelper; -import com.microsoft.bot.schema.models.ResourceResponse; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Represents a bot adapter that can connect a bot to a service endpoint. - * This class is abstract. - * The bot adapter encapsulates authentication processes and sends - * activities to and receives activities from the Bot Connector Service. When your - * bot receives an activity, the adapter creates a context object, passes it to your - * bot's application logic, and sends responses back to the user's channel. - *

Use {@link Use(Middleware)} to add {@link Middleware} objects - * to your adapter’s middleware collection. The adapter processes and directs - * incoming activities in through the bot middleware pipeline to your bot’s logic - * and then back out again. As each activity flows in and out of the bot, each piece - * of middleware can inspect or act upon the activity, both before and after the bot - * logic runs.

- *

- * {@linkalso TurnContext} - * {@linkalso Activity} - * {@linkalso Bot} - * {@linkalso Middleware} - */ -public abstract class BotAdapter { - /** - * The collection of middleware in the adapter's pipeline. - */ - protected final MiddlewareSet _middlewareSet = new MiddlewareSet(); - - /** - * Creates a default adapter. - */ - public BotAdapter() { - super(); - } - - /** - * Adds middleware to the adapter's pipeline. - * - * @param middleware The middleware to add. - * @return The updated adapter object. - * Middleware is added to the adapter at initialization time. - * For each turn, the adapter calls middleware in the order in which you added it. - */ - public BotAdapter Use(Middleware middleware) { - _middlewareSet.Use(middleware); - return this; - } - - /** - * When overridden in a derived class, sends activities to the conversation. - * - * @param context The context object for the turn. - * @param activities The activities to send. - * @return A task that represents the work queued to execute. - * If the activities are successfully sent, the task result contains - * an array of {@link ResourceResponse} objects containing the IDs that - * the receiving channel assigned to the activities. - * {@linkalso TurnContext.OnSendActivities(SendActivitiesHandler)} - */ - public abstract ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException; - - /** - * When overridden in a derived class, replaces an existing activity in the - * conversation. - * - * @param context The context object for the turn. - * @param activity New replacement activity. - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

- * {@linkalso TurnContext.OnUpdateActivity(UpdateActivityHandler)} - */ - public abstract ResourceResponse UpdateActivity(TurnContext context, Activity activity); - - /** - * When overridden in a derived class, deletes an existing activity in the - * conversation. - * - * @param context The context object for the turn. - * @param reference Conversation reference for the activity to delete. - * @return A task that represents the work queued to execute. - * The {@link ConversationReference.ActivityId} of the conversation - * reference identifies the activity to delete. - * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} - */ - public abstract void DeleteActivity(TurnContext context, ConversationReference reference) throws ExecutionException, InterruptedException; - - - /** - * Starts activity processing for the current bot turn. - * - * @param context The turn's context object. - * @param callback A callback method to run at the end of the pipeline. - * @return A task that represents the work queued to execute. - * @throws NullPointerException {@code context} is null. - * The adapter calls middleware in the order in which you added it. - * The adapter passes in the context object for the turn and a next delegate, - * and the middleware calls the delegate to pass control to the next middleware - * in the pipeline. Once control reaches the end of the pipeline, the adapter calls - * the {@code callback} method. If a middleware component doesn’t call - * the next delegate, the adapter does not call any of the subsequent middleware’s - * {@link Middleware.OnTurn(TurnContext, MiddlewareSet.NextDelegate)} - * methods or the callback method, and the pipeline short circuits. - *

When the turn is initiated by a user activity (reactive messaging), the - * callback method will be a reference to the bot's - * {@link Bot.OnTurn(TurnContext)} method. When the turn is - * initiated by a call to {@link ContinueConversation(ConversationReference, Func{TurnContext, Task})} - * (proactive messaging), the callback method is the callback method that was provided in the call.

- */ - protected void RunPipeline(TurnContext context, Consumer callback) throws Exception { - BotAssert.ContextNotNull(context); - - // Call any registered Middleware Components looking for ReceiveActivity() - if (context.getActivity() != null) { - _middlewareSet.ReceiveActivityWithStatus(context, callback); - } else { - // call back to caller on proactive case - if (callback != null) { - callback.accept(context); - } - } - } - - - /** - * Creates a conversation on the specified channel. - * - * @param channelId The ID of the channel. - * @param callback A method to call when the new conversation is available. - * @return A task that represents the work queued to execute. - * @throws UnsupportedOperationException No base implementation is provided. - */ - public CompletableFuture CreateConversation(String channelId, Function callback) { - throw new UnsupportedOperationException("Adapter does not support CreateConversation with this arguments"); - } - - /** - * Sends a proactive message to a conversation. - * - * @param botId The application ID of the bot. This paramter is ignored in - * single tenant the Adpters (Console, Test, etc) but is critical to the BotFrameworkAdapter - * which is multi-tenant aware. - * @param reference A reference to the conversation to continue. - * @param callback The method to call for the resulting bot turn. - * @return A task that represents the work queued to execute. - * Call this method to proactively send a message to a conversation. - * Most channels require a user to initaiate a conversation with a bot - * before the bot can send activities to the user. - * {@linkalso RunPipeline(TurnContext, Func { TurnContext, Task })} - */ - public void ContinueConversation(String botId, ConversationReference reference, Consumer callback) throws Exception { - - ConversationReferenceHelper conv = new ConversationReferenceHelper(reference); - ActivityImpl activity = conv.GetPostToBotMessage(); - - try (TurnContextImpl context = new TurnContextImpl(this, activity)) { - this.RunPipeline(context, callback); - } - } -} +package com.microsoft.bot.builder; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import com.microsoft.bot.schema.*; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Function; + +/** + * Represents a bot adapter that can connect a bot to a service endpoint. + * This class is abstract. + * The bot adapter encapsulates authentication processes and sends + * activities to and receives activities from the Bot Connector Service. When your + * bot receives an activity, the adapter creates a context object, passes it to your + * bot's application logic, and sends responses back to the user's channel. + *

Use {@link Use(Middleware)} to add {@link Middleware} objects + * to your adapter’s middleware collection. The adapter processes and directs + * incoming activities in through the bot middleware pipeline to your bot’s logic + * and then back out again. As each activity flows in and out of the bot, each piece + * of middleware can inspect or act upon the activity, both before and after the bot + * logic runs.

+ *

+ * {@linkalso TurnContext} + * {@linkalso Activity} + * {@linkalso Bot} + * {@linkalso Middleware} + */ +public abstract class BotAdapter { + /** + * The collection of middleware in the adapter's pipeline. + */ + protected final MiddlewareSet _middlewareSet = new MiddlewareSet(); + + /** + * Creates a default adapter. + */ + public BotAdapter() { + super(); + } + + /** + * Adds middleware to the adapter's pipeline. + * + * @param middleware The middleware to add. + * @return The updated adapter object. + * Middleware is added to the adapter at initialization time. + * For each turn, the adapter calls middleware in the order in which you added it. + */ + public BotAdapter Use(Middleware middleware) { + _middlewareSet.Use(middleware); + return this; + } + + /** + * When overridden in a derived class, sends activities to the conversation. + * + * @param context The context object for the turn. + * @param activities The activities to send. + * @return A task that represents the work queued to execute. + * If the activities are successfully sent, the task result contains + * an array of {@link ResourceResponse} objects containing the IDs that + * the receiving channel assigned to the activities. + * {@linkalso TurnContext.OnSendActivities(SendActivitiesHandler)} + */ + public abstract ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException; + + /** + * When overridden in a derived class, replaces an existing activity in the + * conversation. + * + * @param context The context object for the turn. + * @param activity New replacement activity. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

Before calling this, set the ID of the replacement activity to the ID + * of the activity to replace.

+ * {@linkalso TurnContext.OnUpdateActivity(UpdateActivityHandler)} + */ + public abstract ResourceResponse UpdateActivity(TurnContext context, Activity activity); + + /** + * When overridden in a derived class, deletes an existing activity in the + * conversation. + * + * @param context The context object for the turn. + * @param reference Conversation reference for the activity to delete. + * @return A task that represents the work queued to execute. + * The {@link ConversationReference.ActivityId} of the conversation + * reference identifies the activity to delete. + * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} + */ + public abstract void DeleteActivity(TurnContext context, ConversationReference reference) throws ExecutionException, InterruptedException; + + + /** + * Starts activity processing for the current bot turn. + * + * @param context The turn's context object. + * @param callback A callback method to run at the end of the pipeline. + * @return A task that represents the work queued to execute. + * @throws NullPointerException {@code context} is null. + * The adapter calls middleware in the order in which you added it. + * The adapter passes in the context object for the turn and a next delegate, + * and the middleware calls the delegate to pass control to the next middleware + * in the pipeline. Once control reaches the end of the pipeline, the adapter calls + * the {@code callback} method. If a middleware component doesn’t call + * the next delegate, the adapter does not call any of the subsequent middleware’s + * {@link Middleware.OnTurn(TurnContext, MiddlewareSet.NextDelegate)} + * methods or the callback method, and the pipeline short circuits. + *

When the turn is initiated by a user activity (reactive messaging), the + * callback method will be a reference to the bot's + * {@link Bot.OnTurn(TurnContext)} method. When the turn is + * initiated by a call to {@link ContinueConversation(ConversationReference, Func{TurnContext, Task})} + * (proactive messaging), the callback method is the callback method that was provided in the call.

+ */ + protected void RunPipeline(TurnContext context, Consumer callback) throws Exception { + BotAssert.ContextNotNull(context); + + // Call any registered Middleware Components looking for ReceiveActivity() + if (context.getActivity() != null) { + _middlewareSet.ReceiveActivityWithStatus(context, callback); + } else { + // call back to caller on proactive case + if (callback != null) { + callback.accept(context); + } + } + } + + + /** + * Creates a conversation on the specified channel. + * + * @param channelId The ID of the channel. + * @param callback A method to call when the new conversation is available. + * @return A task that represents the work queued to execute. + * @throws UnsupportedOperationException No base implementation is provided. + */ + public CompletableFuture CreateConversation(String channelId, Function callback) { + throw new UnsupportedOperationException("Adapter does not support CreateConversation with this arguments"); + } + + /** + * Sends a proactive message to a conversation. + * + * @param botId The application ID of the bot. This paramter is ignored in + * single tenant the Adpters (Console, Test, etc) but is critical to the BotFrameworkAdapter + * which is multi-tenant aware. + * @param reference A reference to the conversation to continue. + * @param callback The method to call for the resulting bot turn. + * @return A task that represents the work queued to execute. + * Call this method to proactively send a message to a conversation. + * Most channels require a user to initaiate a conversation with a bot + * before the bot can send activities to the user. + * {@linkalso RunPipeline(TurnContext, Func { TurnContext, Task })} + */ + public void ContinueConversation(String botId, ConversationReference reference, Consumer callback) throws Exception { + + ConversationReferenceHelper conv = new ConversationReferenceHelper(reference); + Activity activity = conv.getPostToBotMessage(); + + try (TurnContextImpl context = new TurnContextImpl(this, activity)) { + this.RunPipeline(context, callback); + } + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAssert.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAssert.java index 15a6c15c7..f8a62e947 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAssert.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotAssert.java @@ -1,99 +1,87 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -package com.microsoft.bot.builder; - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; - -import java.util.ArrayList; - -/** - * Provides methods for debugging Bot Builder code. - */ -public class BotAssert -{ - /** - * Checks that an activity object is not {@code null}. - * @param activity The activity object. - * @throws NullPointerException - * {@code activity} is {@code null}. - */ - public static void ActivityNotNull(ActivityImpl activity) - { - if (activity == null) - throw new IllegalArgumentException ("Activity"); - } - - /** - * Checks that an activity object is not {@code null}. - * @param activity The activity object. - * @throws NullPointerException - * {@code activity} is {@code null}. - */ - public static void ActivityNotNull(Activity activity) - { - if (activity == null) - throw new IllegalArgumentException ("Activity"); - } - - /** - * Checks that a context object is not {@code null}. - * @param context The context object. - * @throws NullPointerException - * {@code context} is {@code null}. - */ - public static void ContextNotNull(TurnContext context) - { - if (context == null) - throw new IllegalArgumentException ("TurnContext"); - } - - /** - * Checks that a conversation reference object is not {@code null}. - * @param reference The conversation reference object. - * @throws NullPointerException - * {@code reference} is {@code null}. - */ - public static void ConversationReferenceNotNull(ConversationReference reference) - { - if (reference == null) - throw new IllegalArgumentException ("ConversationReference"); - } - - /** - * Checks that an activity collection is not {@code null}. - * @param activities The activities. - * @throws NullPointerException - * {@code activities} is {@code null}. - */ - public static void ActivityListNotNull(ArrayList activities) - { - if (activities == null) - throw new NullPointerException("List"); - } - - /** - * Checks that a middleware object is not {@code null}. - * @param middleware The middleware object. - * @throws NullPointerException - * {@code middleware} is {@code null}. - */ - public static void MiddlewareNotNull(Middleware middleware) - { - if (middleware == null) - throw new NullPointerException("Middleware"); - } - - /** - * Checks that a middleware collection is not {@code null}. - * @param middleware The middleware. - * @throws NullPointerException - * {@code middleware} is {@code null}. - */ - public static void MiddlewareNotNull(ArrayList middleware) - { - if (middleware == null) - throw new NullPointerException("List"); - } -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ConversationReference; + +import java.util.ArrayList; +import java.util.List; + +/** + * Provides methods for debugging Bot Builder code. + */ +public class BotAssert +{ + /** + * Checks that an activity object is not {@code null}. + * @param activity The activity object. + * @throws NullPointerException + * {@code activity} is {@code null}. + */ + public static void ActivityNotNull(Activity activity) + { + if (activity == null) + throw new IllegalArgumentException ("Activity"); + } + + /** + * Checks that a context object is not {@code null}. + * @param context The context object. + * @throws NullPointerException + * {@code context} is {@code null}. + */ + public static void ContextNotNull(TurnContext context) + { + if (context == null) + throw new IllegalArgumentException ("TurnContext"); + } + + /** + * Checks that a conversation reference object is not {@code null}. + * @param reference The conversation reference object. + * @throws NullPointerException + * {@code reference} is {@code null}. + */ + public static void ConversationReferenceNotNull(ConversationReference reference) + { + if (reference == null) + throw new IllegalArgumentException ("ConversationReference"); + } + + /** + * Checks that an activity collection is not {@code null}. + * @param activities The activities. + * @throws NullPointerException + * {@code activities} is {@code null}. + */ + public static void ActivityListNotNull(List activities) + { + if (activities == null) + throw new NullPointerException("List"); + } + + /** + * Checks that a middleware object is not {@code null}. + * @param middleware The middleware object. + * @throws NullPointerException + * {@code middleware} is {@code null}. + */ + public static void MiddlewareNotNull(Middleware middleware) + { + if (middleware == null) + throw new NullPointerException("Middleware"); + } + + /** + * Checks that a middleware collection is not {@code null}. + * @param middleware The middleware. + * @throws NullPointerException + * {@code middleware} is {@code null}. + */ + public static void MiddlewareNotNull(ArrayList middleware) + { + if (middleware == null) + throw new NullPointerException("List"); + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index bbb50bc4e..8465898fa 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -9,8 +9,7 @@ import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.connector.rest.RestConnectorClient; import com.microsoft.bot.connector.rest.RestConversations; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.*; +import com.microsoft.bot.schema.*; import com.microsoft.rest.retry.RetryStrategy; import org.apache.commons.lang3.StringUtils; import sun.net.www.http.HttpClient; @@ -127,7 +126,7 @@ public void ContinueConversation(String botAppId, ConversationReference referenc if (callback == null) throw new IllegalArgumentException("callback"); - try (TurnContextImpl context = new TurnContextImpl(this, new ConversationReferenceHelper(reference).GetPostToBotMessage())) { + try (TurnContextImpl context = new TurnContextImpl(this, new ConversationReferenceHelper(reference).getPostToBotMessage())) { // Hand craft Claims Identity. HashMap claims = new HashMap(); claims.put(AuthenticationConstants.AUDIENCE_CLAIM, botAppId); @@ -136,7 +135,7 @@ public void ContinueConversation(String botAppId, ConversationReference referenc context.getServices().Add("BotIdentity", claimsIdentity); - ConnectorClient connectorClient = this.CreateConnectorClientAsync(reference.serviceUrl(), claimsIdentity).join(); + ConnectorClient connectorClient = this.CreateConnectorClientAsync(reference.getServiceUrl(), claimsIdentity).join(); context.getServices().Add("ConnectorClient", connectorClient); RunPipeline(context, callback); } @@ -207,7 +206,7 @@ public BotFrameworkAdapter Use(Middleware middleware) { * {@linkalso ContinueConversation(String, ConversationReference, Func { TurnContext, Task })} * {@linkalso BotAdapter.RunPipeline(TurnContext, Func { TurnContext, Task })} */ - public CompletableFuture ProcessActivity(String authHeader, ActivityImpl activity, Function callback) throws Exception { + public CompletableFuture ProcessActivity(String authHeader, Activity activity, Function callback) throws Exception { BotAssert.ActivityNotNull(activity); //ClaimsIdentity claimsIdentity = await(JwtTokenValidation.validateAuthHeader(activity, authHeader, _credentialProvider)); @@ -216,13 +215,13 @@ public CompletableFuture ProcessActivity(String authHeader, Acti return completedFuture(null); } - public CompletableFuture ProcessActivity(ClaimsIdentity identity, ActivityImpl activity, Consumer callback) throws Exception { + public CompletableFuture ProcessActivity(ClaimsIdentity identity, Activity activity, Consumer callback) throws Exception { BotAssert.ActivityNotNull(activity); try (TurnContextImpl context = new TurnContextImpl(this, activity)) { context.getServices().Add("BotIdentity", identity); - ConnectorClient connectorClient = this.CreateConnectorClientAsync(activity.serviceUrl(), identity).join(); + ConnectorClient connectorClient = this.CreateConnectorClientAsync(activity.getServiceUrl(), identity).join(); // TODO: Verify key that C# uses context.getServices().Add("ConnectorClient", connectorClient); @@ -230,13 +229,13 @@ public CompletableFuture ProcessActivity(ClaimsIdentity identity // Handle Invoke scenarios, which deviate from the request/response model in that // the Bot will return a specific body and return code. - if (activity.type() == ActivityTypes.INVOKE) { + if (activity.getType() == ActivityTypes.INVOKE) { Activity invokeResponse = context.getServices().Get(InvokeReponseKey); if (invokeResponse == null) { // ToDo: Trace Here throw new IllegalStateException("Bot failed to return a valid 'invokeResponse' activity."); } else { - return completedFuture((InvokeResponse) invokeResponse.value()); + return completedFuture((InvokeResponse) invokeResponse.getValue()); } } @@ -279,27 +278,27 @@ public ResourceResponse[] SendActivities(TurnContext context, Activity[] activit */ for (int index = 0; index < activities.length; index++) { Activity activity = activities[index]; - ResourceResponse response = new ResourceResponse(); + ResourceResponse response = null; - if (activity.type().toString().equals("delay")) { + if (activity.getType().toString().equals("delay")) { // The Activity Schema doesn't have a delay type build in, so it's simulated // here in the Bot. This matches the behavior in the Node connector. - int delayMs = (int) activity.value(); + int delayMs = (int) activity.getValue(); Thread.sleep(delayMs); //await(Task.Delay(delayMs)); // No need to create a response. One will be created below. - } else if (activity.type().toString().equals("invokeResponse")) // Aligning name with Node + } else if (activity.getType().toString().equals("invokeResponse")) // Aligning name with Node { context.getServices().Add(InvokeReponseKey, activity); // No need to create a response. One will be created below. - } else if (activity.type() == ActivityTypes.TRACE && !activity.channelId().equals("emulator")) { + } else if (activity.getType() == ActivityTypes.TRACE && !activity.getChannelId().equals("emulator")) { // if it is a Trace activity we only send to the channel if it's the emulator. - } else if (!StringUtils.isEmpty(activity.replyToId())) { + } else if (!StringUtils.isEmpty(activity.getReplyToId())) { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().replyToActivity(activity.conversation().id(), activity.id(), activity); + response = connectorClient.conversations().replyToActivity(activity.getConversation().getId(), activity.getId(), activity); } else { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().sendToConversation(activity.conversation().id(), activity); + response = connectorClient.conversations().sendToConversation(activity.getConversation().getId(), activity); } // If No response is set, then defult to a "simple" response. This can't really be done @@ -312,7 +311,7 @@ public ResourceResponse[] SendActivities(TurnContext context, Activity[] activit // https://github.com/Microsoft/botbuilder-dotnet/issues/460 // bug report : https://github.com/Microsoft/botbuilder-dotnet/issues/465 if (response == null) { - response = new ResourceResponse().withId((activity.id() == null) ? "" : activity.id()); + response = new ResourceResponse((activity.getId() == null) ? "" : activity.getId()); } responses[index] = response; @@ -338,7 +337,7 @@ public ResourceResponse[] SendActivities(TurnContext context, Activity[] activit public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); // TODO String conversationId, String activityId, Activity activity) - return connectorClient.conversations().updateActivity(activity.conversation().id(), activity.id(), activity); + return connectorClient.conversations().updateActivity(activity.getConversation().getId(), activity.getId(), activity); } /** @@ -354,7 +353,7 @@ public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { public void DeleteActivity(TurnContext context, ConversationReference reference) { RestConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); try { - connectorClient.conversations().deleteConversationMemberFuture(reference.conversation().id(), reference.activityId()).join(); + connectorClient.conversations().deleteConversationMemberFuture(reference.getConversation().getId(), reference.getActivityId()).join(); } catch (ExecutionException e) { e.printStackTrace(); throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); @@ -373,15 +372,15 @@ public void DeleteActivity(TurnContext context, ConversationReference reference) * @return */ public void DeleteConversationMember(TurnContextImpl context, String memberId) { - if (context.getActivity().conversation() == null) + if (context.getActivity().getConversation() == null) throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation"); - if (StringUtils.isEmpty(context.getActivity().conversation().id())) + if (StringUtils.isEmpty(context.getActivity().getConversation().getId())) throw new IllegalArgumentException("BotFrameworkAdapter.deleteConversationMember(): missing conversation.id"); ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - String conversationId = context.getActivity().conversation().id(); + String conversationId = context.getActivity().getConversation().getId(); // TODO: //await (connectorClient.conversations().DeleteConversationMemberAsync(conversationId, memberId)); @@ -402,16 +401,16 @@ public CompletableFuture> GetActivityMembers(TurnContextImp public CompletableFuture> GetActivityMembers(TurnContextImpl context, String activityId) { // If no activity was passed in, use the current activity. if (activityId == null) - activityId = context.getActivity().id(); + activityId = context.getActivity().getId(); - if (context.getActivity().conversation() == null) + if (context.getActivity().getConversation() == null) throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); - if (StringUtils.isEmpty((context.getActivity().conversation().id()))) + if (StringUtils.isEmpty((context.getActivity().getConversation().getId()))) throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - String conversationId = context.getActivity().conversation().id(); + String conversationId = context.getActivity().getConversation().getId(); // TODO: //List accounts = await(connectorClient.conversations().GetActivityMembersAsync(conversationId, activityId)); @@ -426,14 +425,14 @@ public CompletableFuture> GetActivityMembers(TurnContextImp * @return List of Members of the current conversation */ public CompletableFuture> GetConversationMembers(TurnContextImpl context) { - if (context.getActivity().conversation() == null) + if (context.getActivity().getConversation() == null) throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation"); - if (StringUtils.isEmpty(context.getActivity().conversation().id())) + if (StringUtils.isEmpty(context.getActivity().getConversation().getId())) throw new IllegalArgumentException("BotFrameworkAdapter.GetActivityMembers(): missing conversation.id"); ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - String conversationId = context.getActivity().conversation().id(); + String conversationId = context.getActivity().getConversation().getId(); // TODO //List accounts = await(connectorClient.conversations().getConversationMembersAsync(conversationId)); @@ -510,14 +509,14 @@ public CompletableFuture GetConversations(TurnContextImpl c */ public CompletableFuture GetUserToken(TurnContextImpl context, String connectionName, String magicCode) { BotAssert.ContextNotNull(context); - if (context.getActivity().from() == null || StringUtils.isEmpty(context.getActivity().from().id())) + if (context.getActivity().getFrom() == null || StringUtils.isEmpty(context.getActivity().getFrom().getId())) throw new IllegalArgumentException("BotFrameworkAdapter.GetuserToken(): missing from or from.id"); if (StringUtils.isEmpty(connectionName)) throw new IllegalArgumentException("connectionName"); //OAuthClient client = this.CreateOAuthApiClient(context); - //return await(client.GetUserTokenAsync(context.getActivity().from().id(), connectionName, magicCode)); + //return await(client.GetUserTokenAsync(context.getActivity().getFrom().getId(), connectionName, magicCode)); return completedFuture(null); } @@ -572,7 +571,7 @@ public CompletableFuture SignOutUser(TurnContextImpl context, String connectionN * then sends a {@code conversationUpdate} activity through its middleware pipeline * to the {@code callback} method.

*

If the conversation is established with the - * specified users, the ID of the activity's {@link Activity.Conversation} + * specified users, the ID of the activity's {@link Activity#getConversation} * will contain the ID of the new conversation.

*/ public CompletableFuture CreateConversation(String channelId, String serviceUrl, MicrosoftAppCredentials @@ -605,14 +604,14 @@ public CompletableFuture CreateConversation(String channelId, String serviceUrl, ConversationResourceResponse result = results.get(0); // Create a conversation update activity to represent the result. - ConversationUpdateActivity conversationUpdate = (ConversationUpdateActivity) MessageActivity.CreateConversationUpdateActivity() - .withChannelId(channelId) - .withTopicName(conversationParameters.topicName()) - .withServiceUrl(serviceUrl) - .withMembersAdded(conversationParameters.members()) - .withId((result.activityId() != null) ? result.activityId() : UUID.randomUUID().toString()) - .withConversation(new ConversationAccount().withId(result.id())) - .withRecipient(conversationParameters.bot()); + Activity conversationUpdate = Activity.createConversationUpdateActivity(); + conversationUpdate.setChannelId(channelId); + conversationUpdate.setTopicName(conversationParameters.getTopicName()); + conversationUpdate.setServiceUrl(serviceUrl); + conversationUpdate.setMembersAdded(conversationParameters.getMembers()); + conversationUpdate.setId((result.getActivityId() != null) ? result.getActivityId() : UUID.randomUUID().toString()); + conversationUpdate.setConversation(new ConversationAccount(result.getId())); + conversationUpdate.setRecipient(conversationParameters.getBot()); try (TurnContextImpl context = new TurnContextImpl(this, conversationUpdate)) { try { @@ -635,7 +634,7 @@ public CompletableFuture CreateConversation(String channelId, String serviceUrl, protected CompletableFuture TrySetEmulatingOAuthCards(TurnContext turnContext) { if (!isEmulatingOAuthCards && - turnContext.getActivity().channelId().equals("emulator") && + turnContext.getActivity().getChannelId().equals("emulator") && (_credentialProvider.isAuthenticationDisabledAsync().join())) { isEmulatingOAuthCards = true; } @@ -649,7 +648,7 @@ protected OAuthClient CreateOAuthApiClient(TurnContext context) throws Malformed throw new IllegalArgumentException("CreateOAuthApiClient: OAuth requires a valid ConnectorClient instance"); } if (isEmulatingOAuthCards) { - return new OAuthClient(client, context.getActivity().serviceUrl()); + return new OAuthClient(client, context.getActivity().getServiceUrl()); } return new OAuthClient(client, AuthenticationConstants.OAUTH_URL); } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ConversationState.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ConversationState.java index a802dd94a..b96dfeec0 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ConversationState.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/ConversationState.java @@ -1,49 +1,49 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.builder.TurnContext; - -import java.util.function.Supplier; - -/** - * Handles persistence of a conversation state object using the conversation ID as part of the key. - * @param TState The type of the conversation state object. - */ -public class ConversationState extends BotState -{ - /** - * The key to use to read and write this conversation state object to storage. - */ - // - // Note: Hard coded to maintain compatibility with C# - // "ConversationState:{typeof(ConversationState).Namespace}.{typeof(ConversationState).Name}" - public static String PropertyName() { - return String.format("ConversationState:Microsoft.Bot.Builder.Core.Extensions.ConversationState`1"); - } - - /** - * Creates a new {@link ConversationState{TState}} object. - * @param storage The storage provider to use. - * @param settings The state persistance options to use. - */ - public ConversationState(Storage storage, Supplier ctor) { - this(storage, null, ctor); - } - - public ConversationState(Storage storage, StateSettings settings, Supplier ctor) { - super(storage, PropertyName(), - (context) -> { - return String.format("conversation/%s/%s", context.getActivity().channelId(), context.getActivity().conversation().id()); - }, - ctor, - settings); - } - - /** - * Gets the conversation state object from turn context. - * @param context The context object for this turn. - * @return The coversation state object. - */ - public static TState Get(TurnContext context) throws IllegalArgumentException { - return context.getServices().Get(PropertyName()); - } -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.builder.TurnContext; + +import java.util.function.Supplier; + +/** + * Handles persistence of a conversation state object using the conversation ID as part of the key. + * @param TState The type of the conversation state object. + */ +public class ConversationState extends BotState +{ + /** + * The key to use to read and write this conversation state object to storage. + */ + // + // Note: Hard coded to maintain compatibility with C# + // "ConversationState:{typeof(ConversationState).Namespace}.{typeof(ConversationState).Name}" + public static String PropertyName() { + return String.format("ConversationState:Microsoft.Bot.Builder.Core.Extensions.ConversationState`1"); + } + + /** + * Creates a new {@link ConversationState{TState}} object. + * @param storage The storage provider to use. + * @param settings The state persistance options to use. + */ + public ConversationState(Storage storage, Supplier ctor) { + this(storage, null, ctor); + } + + public ConversationState(Storage storage, StateSettings settings, Supplier ctor) { + super(storage, PropertyName(), + (context) -> { + return String.format("conversation/%s/%s", context.getActivity().getChannelId(), context.getActivity().getConversation().getId()); + }, + ctor, + settings); + } + + /** + * Gets the conversation state object from turn context. + * @param context The context object for this turn. + * @return The coversation state object. + */ + public static TState Get(TurnContext context) throws IllegalArgumentException { + return context.getServices().Get(PropertyName()); + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/DeleteActivityHandler.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/DeleteActivityHandler.java index db6c2568b..2d66c3cc0 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/DeleteActivityHandler.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/DeleteActivityHandler.java @@ -1,25 +1,25 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.schema.models.ConversationReference; - -/** - * A method that can participate in delete activity events for the current turn. - * @param context The context object for the turn. - * @param reference The conversation containing the activity. - * @param next The delegate to call to continue event processing. - * @return A task that represents the work queued to execute. - * A handler calls the {@code next} delegate to pass control to - * the next registered handler. If a handler doesn’t call the next delegate, - * the adapter does not call any of the subsequent handlers and does not delete the - *activity. - *

The conversation reference's {@link ConversationReference.ActivityId} - * indicates the activity in the conversation to replace.

- * - * {@linkalso BotAdapter} - * {@linkalso SendActivitiesHandler} - * {@linkalso UpdateActivityHandler} - */ -@FunctionalInterface -public interface DeleteActivityHandler { - void handle(TurnContext context, ConversationReference reference, Runnable next) throws Exception; -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.ConversationReference; + +/** + * A method that can participate in delete activity events for the current turn. + * @param context The context object for the turn. + * @param reference The conversation containing the activity. + * @param next The delegate to call to continue event processing. + * @return A task that represents the work queued to execute. + * A handler calls the {@code next} delegate to pass control to + * the next registered handler. If a handler doesn’t call the next delegate, + * the adapter does not call any of the subsequent handlers and does not delete the + *activity. + *

The conversation reference's {@link ConversationReference.ActivityId} + * indicates the activity in the conversation to replace.

+ * + * {@linkalso BotAdapter} + * {@linkalso SendActivitiesHandler} + * {@linkalso UpdateActivityHandler} + */ +@FunctionalInterface +public interface DeleteActivityHandler { + void handle(TurnContext context, ConversationReference reference, Runnable next) throws Exception; +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java index 6ddbde3da..4b35f77c5 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/MemoryTranscriptStore.java @@ -6,7 +6,7 @@ import com.microsoft.bot.connector.ExecutorFactory; -import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.Activity; import org.joda.time.DateTime; import java.time.Instant; @@ -18,9 +18,6 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinWorkerThread; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -47,21 +44,21 @@ public final void LogActivityAsync(Activity activity) { synchronized (this.channels) { HashMap> channel; - if (!this.channels.containsKey(activity.channelId())) { + if (!this.channels.containsKey(activity.getChannelId())) { channel = new HashMap>(); - this.channels.put(activity.channelId(), channel); + this.channels.put(activity.getChannelId(), channel); } else { - channel = this.channels.get(activity.channelId()); + channel = this.channels.get(activity.getChannelId()); } ArrayList transcript = null; - if (!channel.containsKey(activity.conversation().id())) { + if (!channel.containsKey(activity.getConversation().getId())) { transcript = new ArrayList(); - channel.put(activity.conversation().id(), transcript); + channel.put(activity.getConversation().getId(), transcript); } else { - transcript = channel.get(activity.conversation().id()); + transcript = channel.get(activity.getConversation().getId()); } transcript.add(activity); @@ -131,9 +128,9 @@ public final CompletableFuture> GetTranscriptActivitiesAsy transcript = channel.get(conversationId); if (continuationToken != null) { List items = transcript.stream() - .sorted(Comparator.comparing(Activity::timestamp)) - .filter(a -> a.timestamp().compareTo(startDate) >= 0) - .filter(skipwhile(a -> !a.id().equals(continuationToken))) + .sorted(Comparator.comparing(Activity::getTimestamp)) + .filter(a -> a.getTimestamp().compareTo(startDate) >= 0) + .filter(skipwhile(a -> !a.getId().equals(continuationToken))) .skip(1) .limit(20) .collect(Collectors.toList()); @@ -141,17 +138,17 @@ public final CompletableFuture> GetTranscriptActivitiesAsy pagedResult.items(items.toArray(new Activity[items.size()])); if (pagedResult.getItems().length == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).id()); + pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); } } else { List items = transcript.stream() - .sorted(Comparator.comparing(Activity::timestamp)) - .filter(a -> a.timestamp().compareTo((startDate == null) ? new DateTime(Long.MIN_VALUE) : startDate) >= 0) + .sorted(Comparator.comparing(Activity::getTimestamp)) + .filter(a -> a.getTimestamp().compareTo((startDate == null) ? new DateTime(Long.MIN_VALUE) : startDate) >= 0) .limit(20) .collect(Collectors.toList()); pagedResult.items(items.toArray(new Activity[items.size()])); if (items.size() == 20) { - pagedResult.withContinuationToken(items.get(items.size() - 1).id()); + pagedResult.withContinuationToken(items.get(items.size() - 1).getId()); } } } @@ -228,7 +225,7 @@ public final CompletableFuture> ListTranscriptsAsync(Str .map(c -> { OffsetDateTime offsetDateTime = null; if (c.getValue().stream().findFirst().isPresent()) { - DateTime dt = c.getValue().stream().findFirst().get().timestamp(); + DateTime dt = c.getValue().stream().findFirst().get().getTimestamp(); // convert to DateTime to OffsetDateTime Instant instant = Instant.ofEpochMilli(dt.getMillis()); ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); @@ -257,7 +254,7 @@ public final CompletableFuture> ListTranscriptsAsync(Str .map(c -> { OffsetDateTime offsetDateTime = null; if (c.getValue().stream().findFirst().isPresent()) { - DateTime dt = c.getValue().stream().findFirst().get().timestamp(); + DateTime dt = c.getValue().stream().findFirst().get().getTimestamp(); // convert to DateTime to OffsetDateTime Instant instant = Instant.ofEpochMilli(dt.getMillis()); ZoneOffset offset = ZoneId.of(dt.getZone().getID()).getRules().getOffset(instant); diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/SendActivitiesHandler.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/SendActivitiesHandler.java index aff09c6f6..61baf4c3b 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/SendActivitiesHandler.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/SendActivitiesHandler.java @@ -1,13 +1,12 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.builder.TurnContext; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ResourceResponse; - -import java.util.List; -import java.util.concurrent.Callable; - -@FunctionalInterface -public interface SendActivitiesHandler { - ResourceResponse[] handle(TurnContext context, List activities, Callable next) throws Exception; -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ResourceResponse; + +import java.util.List; +import java.util.concurrent.Callable; + +@FunctionalInterface +public interface SendActivitiesHandler { + ResourceResponse[] handle(TurnContext context, List activities, Callable next) throws Exception; +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java index 34b67f8ae..48e372934 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TraceTranscriptLogger.java @@ -1,58 +1,45 @@ -package com.microsoft.bot.builder; - - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.microsoft.bot.schema.models.Activity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinWorkerThread; - -/** - * Represents a transcript logger that writes activites to a object. - */ -public class TraceTranscriptLogger implements TranscriptLogger { - // https://github.com/FasterXML/jackson-databind/wiki/Serialization-Features - private static ObjectMapper mapper = new ObjectMapper() - .enable(SerializationFeature.INDENT_OUTPUT); - private static final Logger logger = LoggerFactory.getLogger(TraceTranscriptLogger.class); - - ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() - { - @Override - public ForkJoinWorkerThread newThread(ForkJoinPool pool) - { - final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName("BotTrace-" + worker.getPoolIndex()); - return worker; - } - }; - - ExecutorService executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), factory, null, true); - - /** - * Log an activity to the transcript. - * - * @param activity The activity to transcribe. - * @return A task that represents the work queued to execute. - */ - @Override - public void LogActivityAsync(Activity activity) { - BotAssert.ActivityNotNull(activity); - String event = null; - try { - event = mapper.writeValueAsString(activity); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - this.logger.info(event); - } -} +package com.microsoft.bot.builder; + + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.microsoft.bot.schema.Activity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinWorkerThread; + +/** + * Represents a transcript logger that writes activites to a object. + */ +public class TraceTranscriptLogger implements TranscriptLogger { + // https://github.com/FasterXML/jackson-databind/wiki/Serialization-Features + private static ObjectMapper mapper = new ObjectMapper() + .enable(SerializationFeature.INDENT_OUTPUT); + private static final Logger logger = LoggerFactory.getLogger(TraceTranscriptLogger.class); + + /** + * Log an activity to the transcript. + * + * @param activity The activity to transcribe. + * @return A task that represents the work queued to execute. + */ + @Override + public void LogActivityAsync(Activity activity) { + BotAssert.ActivityNotNull(activity); + String event = null; + try { + event = mapper.writeValueAsString(activity); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + this.logger.info(event); + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLogger.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLogger.java index 4d4204af6..1c368d444 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLogger.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLogger.java @@ -1,21 +1,21 @@ -package com.microsoft.bot.builder; - - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -import com.microsoft.bot.schema.models.Activity; - -/** - * Transcript logger stores activities for conversations for recall. - */ -public interface TranscriptLogger { - /** - * Log an activity to the transcript. - * - * @param activity The activity to transcribe. - * @return A task that represents the work queued to execute. - */ - void LogActivityAsync(Activity activity); -} +package com.microsoft.bot.builder; + + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +import com.microsoft.bot.schema.Activity; + +/** + * Transcript logger stores activities for conversations for recall. + */ +public interface TranscriptLogger { + /** + * Log an activity to the transcript. + * + * @param activity The activity to transcribe. + * @return A task that represents the work queued to execute. + */ + void LogActivityAsync(Activity activity); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java index 1cae34104..68ca44c71 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java @@ -1,191 +1,190 @@ -package com.microsoft.bot.builder; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ActivityTypes; -import com.microsoft.bot.schema.models.ResourceResponse; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; - -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - - -/** - * When added, this middleware will log incoming and outgoing activitites to a ITranscriptStore. - */ -public class TranscriptLoggerMiddleware implements Middleware { - // https://github.com/FasterXML/jackson-databind/wiki/Serialization-Features - private static ObjectMapper mapper; - - static { - mapper = new ObjectMapper() - .enable(SerializationFeature.INDENT_OUTPUT); - mapper.findAndRegisterModules(); - } - - private TranscriptLogger transcriptLogger; - private static final Logger logger = LoggerFactory.getLogger(TranscriptLoggerMiddleware.class); - - private Queue transcript = new ConcurrentLinkedQueue(); - - /** - * Initializes a new instance of the class. - * - * @param transcriptLogger The transcript logger to use. - */ - public TranscriptLoggerMiddleware(TranscriptLogger transcriptLogger) { - if (transcriptLogger == null) - throw new NullPointerException("TranscriptLoggerMiddleware requires a ITranscriptLogger implementation. "); - - this.transcriptLogger = transcriptLogger; - - } - - /** - * initialization for middleware turn. - * - * @param context - * @param next - * @return - */ - @Override - public void OnTurn(TurnContext context, NextDelegate next) throws Exception { - // log incoming activity at beginning of turn - if (context.getActivity() != null) { - JsonNode role = null; - if (context.getActivity().from() == null) { - throw new RuntimeException("Activity does not contain From field"); - } - if (context.getActivity().from().properties().containsKey("role")) { - role = context.getActivity().from().properties().get("role"); - } - - if (role == null || StringUtils.isBlank(role.asText())) { - context.getActivity().from().properties().put("role", mapper.createObjectNode().with("user")); - } - Activity activityTemp = ActivityImpl.CloneActity(context.getActivity()); - - LogActivity(ActivityImpl.CloneActity(context.getActivity())); - } - - // hook up onSend pipeline - context.OnSendActivities((ctx, activities, nextSend) -> - { - - // run full pipeline - ResourceResponse[] responses = new ResourceResponse[0]; - try { - if (nextSend != null) { - responses = nextSend.call(); - } - } catch (Exception e) { - e.printStackTrace(); - } - - for (Activity activity : activities) { - LogActivity(ActivityImpl.CloneActity(activity)); - } - - return responses; - - - }); - - // hook up update activity pipeline - context.OnUpdateActivity((ctx, activity, nextUpdate) -> - { - - // run full pipeline - ResourceResponse response = null; - try { - if (nextUpdate != null) { - response = nextUpdate.call(); - } - } catch (Exception e) { - e.printStackTrace(); - - - throw new RuntimeException(String.format("Error on Logging.OnUpdateActivity : %s", e.toString())); - } - - // add Message Update activity - Activity updateActivity = ActivityImpl.CloneActity(activity); - updateActivity.withType(ActivityTypes.MESSAGE_UPDATE); - LogActivity(updateActivity); - return response; - - - }); - - // hook up delete activity pipeline - context.OnDeleteActivity((ctxt, reference, nextDel) -> { - // run full pipeline - - try { - if (nextDel != null) { - logger.error(String.format("Transcript logActivity next delegate: %s)", nextDel)); - nextDel.run(); - } - } catch (Exception e) { - e.printStackTrace(); - logger.error(String.format("Transcript logActivity failed with %s (next delegate: %s)", e.toString(), nextDel)); - throw new RuntimeException(String.format("Transcript logActivity failed with %s", e.getMessage())); - - } - - // add MessageDelete activity - // log as MessageDelete activity - Activity deleteActivity = new Activity() - .withType(ActivityTypes.MESSAGE_DELETE) - .withId(reference.activityId()) - .applyConversationReference(reference, false); - - LogActivity(deleteActivity); - return; - - }); - - - // process bot logic - try { - next.next(); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Error on Logging.next : %s", e.toString())); - } - - // flush transcript at end of turn - while (!transcript.isEmpty()) { - Activity activity = transcript.poll(); - try { - this.transcriptLogger.LogActivityAsync(activity); - } catch (RuntimeException err) { - logger.error(String.format("Transcript poll failed : %1$s", err)); - } - } - - } - - - private void LogActivity(Activity activity) { - if (activity.timestamp() == null) { - activity.withTimestamp(DateTime.now(DateTimeZone.UTC)); - } - transcript.offer(activity); - } - -} - - - +package com.microsoft.bot.builder; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; +import com.microsoft.bot.schema.ResourceResponse; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + + +/** + * When added, this middleware will log incoming and outgoing activitites to a ITranscriptStore. + */ +public class TranscriptLoggerMiddleware implements Middleware { + // https://github.com/FasterXML/jackson-databind/wiki/Serialization-Features + private static ObjectMapper mapper; + + static { + mapper = new ObjectMapper() + .enable(SerializationFeature.INDENT_OUTPUT); + mapper.findAndRegisterModules(); + } + + private TranscriptLogger transcriptLogger; + private static final Logger logger = LoggerFactory.getLogger(TranscriptLoggerMiddleware.class); + + private Queue transcript = new ConcurrentLinkedQueue(); + + /** + * Initializes a new instance of the class. + * + * @param transcriptLogger The transcript logger to use. + */ + public TranscriptLoggerMiddleware(TranscriptLogger transcriptLogger) { + if (transcriptLogger == null) + throw new NullPointerException("TranscriptLoggerMiddleware requires a ITranscriptLogger implementation. "); + + this.transcriptLogger = transcriptLogger; + + } + + /** + * initialization for middleware turn. + * + * @param context + * @param next + * @return + */ + @Override + public void OnTurn(TurnContext context, NextDelegate next) throws Exception { + // log incoming activity at beginning of turn + if (context.getActivity() != null) { + JsonNode role = null; + if (context.getActivity().getFrom() == null) { + throw new RuntimeException("Activity does not contain From field"); + } + if (context.getActivity().getFrom().getProperties().containsKey("role")) { + role = context.getActivity().getFrom().getProperties().get("role"); + } + + if (role == null || StringUtils.isBlank(role.asText())) { + context.getActivity().getFrom().getProperties().put("role", mapper.createObjectNode().with("user")); + } + Activity activityTemp = Activity.cloneActivity(context.getActivity()); + + LogActivity(Activity.cloneActivity(context.getActivity())); + } + + // hook up onSend pipeline + context.OnSendActivities((ctx, activities, nextSend) -> + { + + // run full pipeline + ResourceResponse[] responses = new ResourceResponse[0]; + try { + if (nextSend != null) { + responses = nextSend.call(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + for (Activity activity : activities) { + LogActivity(Activity.cloneActivity(activity)); + } + + return responses; + + + }); + + // hook up update activity pipeline + context.OnUpdateActivity((ctx, activity, nextUpdate) -> + { + + // run full pipeline + ResourceResponse response = null; + try { + if (nextUpdate != null) { + response = nextUpdate.call(); + } + } catch (Exception e) { + e.printStackTrace(); + + + throw new RuntimeException(String.format("Error on Logging.OnUpdateActivity : %s", e.toString())); + } + + // add Message Update activity + Activity updateActivity = Activity.cloneActivity(activity); + updateActivity.setType(ActivityTypes.MESSAGE_UPDATE); + LogActivity(updateActivity); + return response; + + + }); + + // hook up delete activity pipeline + context.OnDeleteActivity((ctxt, reference, nextDel) -> { + // run full pipeline + + try { + if (nextDel != null) { + logger.error(String.format("Transcript logActivity next delegate: %s)", nextDel)); + nextDel.run(); + } + } catch (Exception e) { + e.printStackTrace(); + logger.error(String.format("Transcript logActivity failed with %s (next delegate: %s)", e.toString(), nextDel)); + throw new RuntimeException(String.format("Transcript logActivity failed with %s", e.getMessage())); + + } + + // add MessageDelete activity + // log as MessageDelete activity + Activity deleteActivity = new Activity(ActivityTypes.MESSAGE_DELETE) {{ + setId(reference.getActivityId()); + applyConversationReference(reference, false); + }}; + + LogActivity(deleteActivity); + return; + + }); + + + // process bot logic + try { + next.next(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Error on Logging.next : %s", e.toString())); + } + + // flush transcript at end of turn + while (!transcript.isEmpty()) { + Activity activity = transcript.poll(); + try { + this.transcriptLogger.LogActivityAsync(activity); + } catch (RuntimeException err) { + logger.error(String.format("Transcript poll failed : %1$s", err)); + } + } + + } + + + private void LogActivity(Activity activity) { + if (activity.getTimestamp() == null) { + activity.setTimestamp(DateTime.now(DateTimeZone.UTC)); + } + transcript.offer(activity); + } + +} + + + diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptStore.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptStore.java index 085a294f2..2a5e856a1 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptStore.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptStore.java @@ -1,57 +1,57 @@ -package com.microsoft.bot.builder; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -import com.microsoft.bot.schema.models.Activity; -import org.joda.time.DateTime; - -import java.util.concurrent.CompletableFuture; - -/** - * Transcript logger stores activities for conversations for recall. - */ -public interface TranscriptStore extends TranscriptLogger { - /** - * Gets from the store activities that match a set of criteria. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation. - * @param continuationToken - * @param startDate A cutoff date. Activities older than this date are not included. - * @return A task that represents the work queued to execute. - * If the task completes successfully, the result contains the matching activities. - */ - - CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken); - - CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId); - - //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: -//ORIGINAL LINE: Task> GetTranscriptActivitiesAsync(string channelId, string conversationId, string continuationToken = null, DateTime startDate = default(DateTime)); - CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken, DateTime localStartDate); - - /** - * Gets the conversations on a channel from the store. - * - * @param channelId The ID of the channel. - * @param continuationToken - * @return A task that represents the work queued to execute. - */ - - CompletableFuture> ListTranscriptsAsync(String channelId); - - //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: -//ORIGINAL LINE: Task> ListTranscriptsAsync(string channelId, string continuationToken = null); - CompletableFuture> ListTranscriptsAsync(String channelId, String continuationToken); - - /** - * Deletes conversation data from the store. - * - * @param channelId The ID of the channel the conversation is in. - * @param conversationId The ID of the conversation to delete. - * @return A task that represents the work queued to execute. - */ - CompletableFuture DeleteTranscriptAsync(String channelId, String conversationId); -} +package com.microsoft.bot.builder; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +import com.microsoft.bot.schema.Activity; +import org.joda.time.DateTime; + +import java.util.concurrent.CompletableFuture; + +/** + * Transcript logger stores activities for conversations for recall. + */ +public interface TranscriptStore extends TranscriptLogger { + /** + * Gets from the store activities that match a set of criteria. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation. + * @param continuationToken + * @param startDate A cutoff date. Activities older than this date are not included. + * @return A task that represents the work queued to execute. + * If the task completes successfully, the result contains the matching activities. + */ + + CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken); + + CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId); + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: +//ORIGINAL LINE: Task> GetTranscriptActivitiesAsync(string channelId, string conversationId, string continuationToken = null, DateTime startDate = default(DateTime)); + CompletableFuture> GetTranscriptActivitiesAsync(String channelId, String conversationId, String continuationToken, DateTime localStartDate); + + /** + * Gets the conversations on a channel from the store. + * + * @param channelId The ID of the channel. + * @param continuationToken + * @return A task that represents the work queued to execute. + */ + + CompletableFuture> ListTranscriptsAsync(String channelId); + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: +//ORIGINAL LINE: Task> ListTranscriptsAsync(string channelId, string continuationToken = null); + CompletableFuture> ListTranscriptsAsync(String channelId, String continuationToken); + + /** + * Deletes conversation data from the store. + * + * @param channelId The ID of the channel the conversation is in. + * @param conversationId The ID of the conversation to delete. + * @return A task that represents the work queued to execute. + */ + CompletableFuture DeleteTranscriptAsync(String channelId, String conversationId); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContext.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContext.java index edf6ced6a..90337f4be 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContext.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContext.java @@ -1,182 +1,214 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -package com.microsoft.bot.builder; - -/** - * A method that can participate in send activity events for the current turn. - * @param context The context object for the turn. - * @param activities The activities to send. - * @param next The delegate to call to continue event processing. - * @return A task that represents the work queued to execute. - * A handler calls the {@code next} delegate to pass control to - * the next registered handler. If a handler doesn’t call the next delegate, - * the adapter does not call any of the subsequent handlers and does not send the - * {@code activities}. - * - * {@linkalso BotAdapter} - * {@linkalso UpdateActivityHandler} - * {@linkalso DeleteActivityHandler} - */ - -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.ResourceResponse; - -import java.util.concurrent.CompletableFuture; - -//public delegate Task DeleteActivityHandler(TurnContext context, ConversationReference reference, Func next); - -/** - * Provides context for a turn of a bot. - * Context provides information needed to process an incoming activity. - * The context object is created by a {@link BotAdapter} and persists for the - * length of the turn. - * {@linkalso Bot} - * {@linkalso Middleware} - */ -public interface TurnContext -{ - /** - * Gets the bot adapter that created this context object. - */ - BotAdapter getAdapter(); - - /** - * Gets the services registered on this context object. - */ - TurnContextServiceCollection getServices(); - - /** - * Incoming request - */ - Activity getActivity(); - - - - /** - * Indicates whether at least one response was sent for the current turn. - * @return {@code true} if at least one response was sent for the current turn. - */ - boolean getResponded(); - void setResponded(boolean responded); - - /** - * Sends a message activity to the sender of the incoming activity. - * @param textReplyToSend The text of the message to send. - * @param speak Optional, text to be spoken by your bot on a speech-enabled - * channel. - * @param inputHint Optional, indicates whether your bot is accepting, - * expecting, or ignoring user input after the message is delivered to the client. - * One of: "acceptingInput", "ignoringInput", or "expectingInput". - * Default is "acceptingInput". - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

See the channel's documentation for limits imposed upon the contents of - * {@code textReplyToSend}.

- *

To control various characteristics of your bot's speech such as voice, - * rate, volume, pronunciation, and pitch, specify {@code speak} in - * Speech Synthesis Markup Language (SSML) format.

- * - */ - ResourceResponse SendActivity(String textReplyToSend) throws Exception; - ResourceResponse SendActivity(String textReplyToSend, String speak) throws Exception; - //CompletableFuture SendActivity(String textReplyToSend, String speak = null, String inputHint = InputHints.AcceptingInput); - ResourceResponse SendActivity(String textReplyToSend, String speak, String inputHint) throws Exception; - - /** - * Sends an activity to the sender of the incoming activity. - * @param activity The activity to send. - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - */ - ResourceResponse SendActivity(Activity activity) throws Exception; - - /** - * Sends a set of activities to the sender of the incoming activity. - * @param activities The activities to send. - * @return A task that represents the work queued to execute. - * If the activities are successfully sent, the task result contains - * an array of {@link ResourceResponse} objects containing the IDs that - * the receiving channel assigned to the activities. - */ - ResourceResponse[] SendActivities(Activity[] activities) throws Exception; - - /** - * Replaces an existing activity. - * @param activity New replacement activity. - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

- */ - ResourceResponse UpdateActivity(Activity activity) throws Exception; - - /** - * Replaces an existing activity. - * @param activity New replacement activity. - * @return A task that represents the work queued to execute. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

- */ - //CompletableFuture UpdateActivityAsync(Activity activity) throws Exception; - - /** - * Deletes an existing activity. - * @param activityId The ID of the activity to delete. - * @return A task that represents the work queued to execute. - */ - CompletableFuture DeleteActivity(String activityId) throws Exception; - - /** - * Deletes an existing activity. - * @param conversationReference The conversation containing the activity to delete. - * @return A task that represents the work queued to execute. - * The conversation reference's {@link ConversationReference.ActivityId} - * indicates the activity in the conversation to delete. - */ - void DeleteActivity(ConversationReference conversationReference) throws Exception; - - /** - * Adds a response handler for send activity operations. - * @param handler The handler to add to the context object. - * @return The updated context object. - * When the context's {@link SendActivity(Activity)} - * or {@link SendActivities(Activity[])} methods are called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - * - */ - TurnContext OnSendActivities(SendActivitiesHandler handler); - - /** - * Adds a response handler for update activity operations. - * @param handler The handler to add to the context object. - * @return The updated context object. - * When the context's {@link UpdateActivity(Activity)} is called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - * - */ - TurnContext OnUpdateActivity(UpdateActivityHandler handler); - - /** - * Adds a response handler for delete activity operations. - * @param handler The handler to add to the context object. - * @return The updated context object. - * @throws NullPointerException {@code handler} is {@code null}. - * When the context's {@link DeleteActivity(String)} is called, - * the adapter calls the registered handlers in the order in which they were - * added to the context object. - * - */ - TurnContext OnDeleteActivity(DeleteActivityHandler handler); -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.bot.builder; + +/** + * A method that can participate in send activity events for the current turn. + * @param context The context object for the turn. + * @param activities The activities to send. + * @param next The delegate to call to continue event processing. + * @return A task that represents the work queued to execute. + * A handler calls the {@code next} delegate to pass control to + * the next registered handler. If a handler doesn’t call the next delegate, + * the adapter does not call any of the subsequent handlers and does not send the + * {@code activities}. + * + * {@linkalso BotAdapter} + * {@linkalso UpdateActivityHandler} + * {@linkalso DeleteActivityHandler} + */ + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ConversationReference; +import com.microsoft.bot.schema.ResourceResponse; + +import java.util.concurrent.CompletableFuture; + +//public delegate Task DeleteActivityHandler(TurnContext context, ConversationReference reference, Func next); + +/** + * Provides context for a turn of a bot. + * Context provides information needed to process an incoming activity. + * The context object is created by a {@link BotAdapter} and persists for the + * length of the turn. + * {@linkalso Bot} + * {@linkalso Middleware} + */ +public interface TurnContext +{ + /** + * Gets the bot adapter that created this context object. + */ + BotAdapter getAdapter(); + + /** + * Gets the services registered on this context object. + */ + TurnContextServiceCollection getServices(); + + /** + * Incoming request + */ + Activity getActivity(); + + + + /** + * Indicates whether at least one response was sent for the current turn. + * @return {@code true} if at least one response was sent for the current turn. + */ + boolean getResponded(); + void setResponded(boolean responded); + + /** + * Sends a message activity to the sender of the incoming activity. + * @param textReplyToSend The text of the message to send. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

See the channel's documentation for limits imposed upon the contents of + * {@code textReplyToSend}.

+ *

To control various characteristics of your bot's speech such as voice, + * rate, volume, pronunciation, and pitch, specify {@code speak} in + * Speech Synthesis Markup Language (SSML) format.

+ * + */ + ResourceResponse SendActivity(String textReplyToSend) throws Exception; + + /** + * Sends a message activity to the sender of the incoming activity. + * @param textReplyToSend The text of the message to send. + * @param speak Optional, text to be spoken by your bot on a speech-enabled + * channel. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

See the channel's documentation for limits imposed upon the contents of + * {@code textReplyToSend}.

+ *

To control various characteristics of your bot's speech such as voice, + * rate, volume, pronunciation, and pitch, specify {@code speak} in + * Speech Synthesis Markup Language (SSML) format.

+ * + */ + ResourceResponse SendActivity(String textReplyToSend, String speak) throws Exception; + //CompletableFuture SendActivity(String textReplyToSend, String speak = null, String inputHint = InputHints.AcceptingInput); + + /** + * Sends a message activity to the sender of the incoming activity. + * @param textReplyToSend The text of the message to send. + * @param speak Optional, text to be spoken by your bot on a speech-enabled + * channel. + * @param inputHint Optional, indicates whether your bot is accepting, + * expecting, or ignoring user input after the message is delivered to the client. + * One of: "acceptingInput", "ignoringInput", or "expectingInput". + * Default is "acceptingInput". + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

See the channel's documentation for limits imposed upon the contents of + * {@code textReplyToSend}.

+ *

To control various characteristics of your bot's speech such as voice, + * rate, volume, pronunciation, and pitch, specify {@code speak} in + * Speech Synthesis Markup Language (SSML) format.

+ * + */ + ResourceResponse SendActivity(String textReplyToSend, String speak, String inputHint) throws Exception; + + /** + * Sends an activity to the sender of the incoming activity. + * @param activity The activity to send. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + */ + ResourceResponse SendActivity(Activity activity) throws Exception; + + /** + * Sends a set of activities to the sender of the incoming activity. + * @param activities The activities to send. + * @return A task that represents the work queued to execute. + * If the activities are successfully sent, the task result contains + * an array of {@link ResourceResponse} objects containing the IDs that + * the receiving channel assigned to the activities. + */ + ResourceResponse[] SendActivities(Activity[] activities) throws Exception; + + /** + * Replaces an existing activity. + * @param activity New replacement activity. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

Before calling this, set the ID of the replacement activity to the ID + * of the activity to replace.

+ */ + ResourceResponse UpdateActivity(Activity activity) throws Exception; + + /** + * Replaces an existing activity. + * @param activity New replacement activity. + * @return A task that represents the work queued to execute. + * If the activity is successfully sent, the task result contains + * a {@link ResourceResponse} object containing the ID that the receiving + * channel assigned to the activity. + *

Before calling this, set the ID of the replacement activity to the ID + * of the activity to replace.

+ */ + //CompletableFuture UpdateActivityAsync(Activity activity) throws Exception; + + /** + * Deletes an existing activity. + * @param activityId The ID of the activity to delete. + * @return A task that represents the work queued to execute. + */ + CompletableFuture DeleteActivity(String activityId) throws Exception; + + /** + * Deletes an existing activity. + * @param conversationReference The conversation containing the activity to delete. + * @return A task that represents the work queued to execute. + * The conversation reference's {@link ConversationReference#getActivityId} + * indicates the activity in the conversation to delete. + */ + void DeleteActivity(ConversationReference conversationReference) throws Exception; + + /** + * Adds a response handler for send activity operations. + * @param handler The handler to add to the context object. + * @return The updated context object. + * When the context's {@link #SendActivity( Activity )} + * or {@link #SendActivities( Activity[])} methods are called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + * + */ + TurnContext OnSendActivities(SendActivitiesHandler handler); + + /** + * Adds a response handler for update activity operations. + * @param handler The handler to add to the context object. + * @return The updated context object. + * When the context's {@link #UpdateActivity( Activity )} is called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + * + */ + TurnContext OnUpdateActivity(UpdateActivityHandler handler); + + /** + * Adds a response handler for delete activity operations. + * @param handler The handler to add to the context object. + * @return The updated context object. + * @throws NullPointerException {@code handler} is {@code null}. + * When the context's {@link #DeleteActivity(String)} is called, + * the adapter calls the registered handlers in the order in which they were + * added to the context object. + * + */ + TurnContext OnDeleteActivity(DeleteActivityHandler handler); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java index 315248a0e..57fc3dcb8 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TurnContextImpl.java @@ -4,11 +4,10 @@ // Licensed under the MIT License. import com.microsoft.bot.connector.ExecutorFactory; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.InputHints; -import com.microsoft.bot.schema.models.ResourceResponse; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ConversationReference; +import com.microsoft.bot.schema.InputHints; +import com.microsoft.bot.schema.ResourceResponse; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -17,8 +16,8 @@ import java.util.List; import java.util.concurrent.*; -import static com.microsoft.bot.schema.models.ActivityTypes.MESSAGE; -import static com.microsoft.bot.schema.models.ActivityTypes.TRACE; +import static com.microsoft.bot.schema.ActivityTypes.MESSAGE; +import static com.microsoft.bot.schema.ActivityTypes.TRACE; import static java.util.stream.Collectors.toList; /** @@ -31,7 +30,7 @@ */ public class TurnContextImpl implements TurnContext, AutoCloseable { private final BotAdapter adapter; - private final ActivityImpl activity; + private final Activity activity; private Boolean responded = false; private final List onSendActivities = new ArrayList(); @@ -50,7 +49,7 @@ public class TurnContextImpl implements TurnContext, AutoCloseable { * {@code adapter} is {@code null}. * For use by bot adapter implementations only. */ - public TurnContextImpl(BotAdapter adapter, ActivityImpl activity) { + public TurnContextImpl(BotAdapter adapter, Activity activity) { if (adapter == null) throw new IllegalArgumentException("adapter"); this.adapter = adapter; @@ -68,8 +67,8 @@ public TurnContextImpl(BotAdapter adapter, ActivityImpl activity) { * @param handler The handler to add to the context object. * @return The updated context object. * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link SendActivity(Activity)} - * or {@link SendActivities(Activity[])} methods are called, + * When the context's {@link #SendActivity( Activity )} + * or {@link #SendActivities( Activity[])} methods are called, * the adapter calls the registered handlers in the order in which they were * added to the context object. */ @@ -87,7 +86,7 @@ public TurnContextImpl OnSendActivities(SendActivitiesHandler handler) { * @param handler The handler to add to the context object. * @return The updated context object. * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link UpdateActivity(Activity)} is called, + * When the context's {@link #UpdateActivity( Activity )} is called, * the adapter calls the registered handlers in the order in which they were * added to the context object. */ @@ -105,7 +104,7 @@ public TurnContextImpl OnUpdateActivity(UpdateActivityHandler handler) { * @param handler The handler to add to the context object. * @return The updated context object. * @throws IllegalArgumentException {@code handler} is {@code null}. - * When the context's {@link DeleteActivity(string)} is called, + * When the context's {@link #DeleteActivity(String)} is called, * the adapter calls the registered handlers in the order in which they were * added to the context object. */ @@ -161,12 +160,6 @@ public void setResponded(boolean responded) { * Sends a message activity to the sender of the incoming activity. * * @param textReplyToSend The text of the message to send. - * @param speak Optional, text to be spoken by your bot on a speech-enabled - * channel. - * @param inputHint Optional, indicates whether your bot is accepting, - * expecting, or ignoring user input after the message is delivered to the client. - * One of: "acceptingInput", "ignoringInput", or "expectingInput". - * Default is null. * @return A task that represents the work queued to execute. * @throws IllegalArgumentException {@code textReplyToSend} is {@code null} or whitespace. * If the activity is successfully sent, the task result contains @@ -193,14 +186,14 @@ public ResourceResponse SendActivity(String textReplyToSend, String speak, Strin if (StringUtils.isEmpty(textReplyToSend)) throw new IllegalArgumentException("textReplyToSend"); - ActivityImpl activityToSend = (ActivityImpl) new ActivityImpl() - .withType(MESSAGE) - .withText(textReplyToSend); + Activity activityToSend = (Activity) new Activity(MESSAGE) {{ + setText(textReplyToSend); + }}; if (speak != null) - activityToSend.withSpeak(speak); + activityToSend.setSpeak(speak); if (StringUtils.isNotEmpty(inputHint)) - activityToSend.withInputHint(InputHints.fromString(inputHint)); + activityToSend.setInputHint(InputHints.fromString(inputHint)); return SendActivity(activityToSend); } @@ -260,7 +253,7 @@ public ResourceResponse[] SendActivities(Activity[] activities) throws Exception // Convert the IActivities to Activies. // Activity[] activityArray = Array.ConvertAll(activities, (input) => (Activity)input); - List activityArray = Arrays.stream(activities).map(input -> (Activity) input).collect(toList()); + List activityArray = Arrays.stream(activities).map(input -> input).collect(toList()); // Create the list used by the recursive methods. @@ -272,20 +265,20 @@ public ResourceResponse[] SendActivities(Activity[] activities) throws Exception // so the "Responded" flag should not be set by Trace messages being // sent out. boolean sentNonTraceActivities = false; - if (!activityList.stream().anyMatch((a) -> a.type() == TRACE)) { + if (!activityList.stream().anyMatch((a) -> a.getType() == TRACE)) { sentNonTraceActivities = true; } // Send from the list, which may have been manipulated via the event handlers. // Note that 'responses' was captured from the root of the call, and will be // returned to the original caller. ResourceResponse[] responses = new ResourceResponse[0]; - responses = this.getAdapter().SendActivities(this, activityList.toArray(new ActivityImpl[activityList.size()])); + responses = this.getAdapter().SendActivities(this, activityList.toArray(new Activity[activityList.size()])); if (responses != null && responses.length == activityList.size()) { // stitch up activity ids for (int i = 0; i < responses.length; i++) { ResourceResponse response = responses[i]; Activity activity = activityList.get(i); - activity.withId(response.id()); + activity.setId(response.getId()); } } @@ -305,13 +298,7 @@ public ResourceResponse[] SendActivities(Activity[] activities) throws Exception * * @param activity New replacement activity. * @return A task that represents the work queued to execute. - * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. - * @throws System.AggregateException One or more exceptions occurred during the operation. - * If the activity is successfully sent, the task result contains - * a {@link ResourceResponse} object containing the ID that the receiving - * channel assigned to the activity. - *

Before calling this, set the ID of the replacement activity to the ID - * of the activity to replace.

+ * @throws com.microsoft.bot.connector.rest.ErrorResponseException The HTTP operation failed and the response contained additional information. */ @Override public ResourceResponse UpdateActivity(Activity activity) throws Exception { @@ -339,7 +326,7 @@ public CompletableFuture DeleteActivity(String activityId) throws Exceptio return CompletableFuture.runAsync(() -> { ConversationReference cr = this.GetConversationReference(this.getActivity()); - cr.withActivityId(activityId); + cr.setActivityId(activityId); Runnable ActuallyDeleteStuff = () -> { try { @@ -371,8 +358,8 @@ public CompletableFuture DeleteActivity(String activityId) throws Exceptio * * @param conversationReference The conversation containing the activity to delete. * @return A task that represents the work queued to execute. - * @throws Microsoft.Bot.Schema.ErrorResponseException The HTTP operation failed and the response contained additional information. - * The conversation reference's {@link ConversationReference.ActivityId} + * @throws com.microsoft.bot.connector.rest.ErrorResponseException The HTTP operation failed and the response contained additional information. + * The conversation reference's {@link ConversationReference#getActivityId} * indicates the activity in the conversation to delete. */ public void DeleteActivity(ConversationReference conversationReference) throws Exception { @@ -463,8 +450,8 @@ private ResourceResponse[] SendActivitiesInternal(List activities, Ite // return await toCall(this, activity, next); // } private ResourceResponse UpdateActivityInternal(Activity activity, - Iterator updateHandlers, - Callable callAtBottom) throws Exception { + Iterator updateHandlers, + Callable callAtBottom) throws Exception { BotAssert.ActivityNotNull(activity); if (updateHandlers == null) throw new IllegalArgumentException("updateHandlers"); @@ -489,7 +476,7 @@ private ResourceResponse UpdateActivityInternal(Activity activity, e.printStackTrace(); throw new RuntimeException(String.format("Error updating activity: %s", e.toString())); } - activity.withId(result.id()); + activity.setId(result.getId()); return result; }; @@ -547,17 +534,29 @@ private void DeleteActivityInternal(ConversationReference cr, public static ConversationReference GetConversationReference(Activity activity) { BotAssert.ActivityNotNull(activity); - ConversationReference r = new ConversationReference() - .withActivityId(activity.id()) - .withUser(activity.from()) - .withBot(activity.recipient()) - .withConversation(activity.conversation()) - .withChannelId(activity.channelId()) - .withServiceUrl(activity.serviceUrl()); + ConversationReference r = new ConversationReference() {{ + setActivityId(activity.getId()); + setUser(activity.getFrom()); + setBot(activity.getRecipient()); + setConversation(activity.getConversation()); + setChannelId(activity.getChannelId()); + setServiceUrl(activity.getServiceUrl()); + }}; return r; } + /** + * Updates an activity with the delivery information from an existing + * conversation reference. + * + * @param activity The activity to update. + * @param reference The conversation reference. + */ + public static Activity ApplyConversationReference(Activity activity, ConversationReference reference) { + return ApplyConversationReference(activity, reference, false); + } + /** * Updates an activity with the delivery information from an existing * conversation reference. @@ -567,31 +566,27 @@ public static ConversationReference GetConversationReference(Activity activity) * @param isIncoming (Optional) {@code true} to treat the activity as an * incoming activity, where the bot is the recipient; otherwaire {@code false}. * Default is {@code false}, and the activity will show the bot as the sender. - * Call {@link GetConversationReference(Activity)} on an incoming + * Call {@link #GetConversationReference( Activity )} on an incoming * activity to get a conversation reference that you can then use to update an * outgoing activity with the correct delivery information. - *

The {@link SendActivity(Activity)} and {@link SendActivities(Activity[])} + *

The {@link #SendActivity( Activity )} and {@link #SendActivities( Activity[])} * methods do this for you.

*/ - public static Activity ApplyConversationReference(Activity activity, ConversationReference reference) { - return ApplyConversationReference(activity, reference, false); - } - public static Activity ApplyConversationReference(Activity activity, ConversationReference reference, boolean isIncoming) { - activity.withChannelId(reference.channelId()); - activity.withServiceUrl(reference.serviceUrl()); - activity.withConversation(reference.conversation()); + activity.setChannelId(reference.getChannelId()); + activity.setServiceUrl(reference.getServiceUrl()); + activity.setConversation(reference.getConversation()); if (isIncoming) { - activity.withFrom(reference.user()); - activity.withRecipient(reference.bot()); - if (reference.activityId() != null) - activity.withId(reference.activityId()); + activity.setFrom(reference.getUser()); + activity.setRecipient(reference.getBot()); + if (reference.getActivityId() != null) + activity.setId(reference.getActivityId()); } else { // Outgoing - activity.withFrom(reference.bot()); - activity.withRecipient(reference.user()); - if (reference.activityId() != null) - activity.withReplyToId(reference.activityId()); + activity.setFrom(reference.getBot()); + activity.setRecipient(reference.getUser()); + if (reference.getActivityId() != null) + activity.setReplyToId(reference.getActivityId()); } return activity; } diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UpdateActivityHandler.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UpdateActivityHandler.java index fc62d63d7..4fc00d1be 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UpdateActivityHandler.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UpdateActivityHandler.java @@ -1,30 +1,28 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.builder.TurnContext; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ResourceResponse; - -import java.util.concurrent.Callable; - -/** - * A method that can participate in update activity events for the current turn. - * @param context The context object for the turn. - * @param activity The replacement activity. - * @param next The delegate to call to continue event processing. - * @return A task that represents the work queued to execute. - * A handler calls the {@code next} delegate to pass control to - * the next registered handler. If a handler doesn’t call the next delegate, - * the adapter does not call any of the subsequent handlers and does not update the - * activity. - *

The activity's {@link Activity.Id} indicates the activity in the - * conversation to replace.

- * - * {@linkalso BotAdapter} - * {@linkalso SendActivitiesHandler} - * {@linkalso DeleteActivityHandler} - */ - -@FunctionalInterface -public interface UpdateActivityHandler { - ResourceResponse handle(TurnContext context, Activity activity, Callable next); -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ResourceResponse; + +import java.util.concurrent.Callable; + +@FunctionalInterface +public interface UpdateActivityHandler { + /** + * A method that can participate in update activity events for the current turn. + * @param context The context object for the turn. + * @param activity The replacement activity. + * @param next The delegate to call to continue event processing. + * @return A task that represents the work queued to execute. + * A handler calls the {@code next} delegate to pass control to + * the next registered handler. If a handler doesn’t call the next delegate, + * the adapter does not call any of the subsequent handlers and does not update the + * activity. + *

The activity's {@link Activity#getId} indicates the activity in the + * conversation to replace.

+ * + * {@linkalso BotAdapter} + * {@linkalso SendActivitiesHandler} + * {@linkalso DeleteActivityHandler} + */ + ResourceResponse handle(TurnContext context, Activity activity, Callable next); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java index 1b37447a0..9088e1d9e 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/UserState.java @@ -1,50 +1,50 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.builder.StateSettings; -import com.microsoft.bot.builder.Storage; -import com.microsoft.bot.builder.TurnContext; - - -import java.util.function.Supplier; - -/** - * Handles persistence of a user state object using the user ID as part of the key. - * @param TState The type of the user state object. - */ -public class UserState extends BotState -{ - /** - * The key to use to read and write this conversation state object to storage. - */ - // Note: Hard coded to maintain compatibility with C# - // "UserState:{typeof(UserState).Namespace}.{typeof(UserState).Name}" - public static String PropertyName() { - return String.format("UserState:Microsoft.Bot.Builder.Core.Extensions.UserState`1"); - } - - /** - * Creates a new {@link UserState{TState}} object. - * @param storage The storage provider to use. - * @param settings The state persistance options to use. - */ - public UserState(Storage storage, Supplier ctor) { - this(storage, ctor, null); - } - public UserState(Storage storage, Supplier ctor, StateSettings settings) { - super(storage, PropertyName(), - (context) -> { - return String.format("user/%s/%s", context.getActivity().channelId(), context.getActivity().conversation().id()); - }, - ctor, - settings); - } - - /** - * Gets the user state object from turn context. - * @param context The context object for this turn. - * @return The user state object. - */ - public static TState Get(TurnContext context) throws IllegalArgumentException { - return context.getServices().Get(PropertyName()); - } -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.builder.StateSettings; +import com.microsoft.bot.builder.Storage; +import com.microsoft.bot.builder.TurnContext; + + +import java.util.function.Supplier; + +/** + * Handles persistence of a user state object using the user ID as part of the key. + * @param TState The type of the user state object. + */ +public class UserState extends BotState +{ + /** + * The key to use to read and write this conversation state object to storage. + */ + // Note: Hard coded to maintain compatibility with C# + // "UserState:{typeof(UserState).Namespace}.{typeof(UserState).Name}" + public static String PropertyName() { + return String.format("UserState:Microsoft.Bot.Builder.Core.Extensions.UserState`1"); + } + + /** + * Creates a new {@link UserState{TState}} object. + * @param storage The storage provider to use. + * @param settings The state persistance options to use. + */ + public UserState(Storage storage, Supplier ctor) { + this(storage, ctor, null); + } + public UserState(Storage storage, Supplier ctor, StateSettings settings) { + super(storage, PropertyName(), + (context) -> { + return String.format("user/%s/%s", context.getActivity().getChannelId(), context.getActivity().getConversation().getId()); + }, + ctor, + settings); + } + + /** + * Gets the user state object from turn context. + * @param context The context object for this turn. + * @return The user state object. + */ + public static TState Get(TurnContext context) throws IllegalArgumentException { + return context.getServices().Get(PropertyName()); + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/adapters/TestAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/adapters/TestAdapter.java index 7b2ea9935..1eaf8658d 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/adapters/TestAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/adapters/TestAdapter.java @@ -1,234 +1,237 @@ -package com.microsoft.bot.builder.adapters; - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import com.microsoft.bot.builder.BotAdapter; -import com.microsoft.bot.builder.Middleware; -import com.microsoft.bot.builder.TurnContext; -import com.microsoft.bot.builder.TurnContextImpl; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.*; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; -import java.util.function.Function; - -public class TestAdapter extends BotAdapter { - private int nextId = 0; - private final Queue botReplies = new LinkedList<>(); - private ConversationReference conversationReference; - - public TestAdapter() { - this(null); - } - - - public TestAdapter(ConversationReference reference) { - if (reference != null) { - this.withConversationReference(reference); - } else { - this.withConversationReference(new ConversationReference() - .withChannelId("test") - .withServiceUrl("https://test.com")); - - this.conversationReference().withUser(new ChannelAccount() - .withId("user1") - .withName("User1")); - this.conversationReference().withBot(new ChannelAccount() - .withId("bot") - .withName("Bot")); - this.conversationReference().withConversation(new ConversationAccount() - .withIsGroup(Boolean.FALSE) - .withConversationType("convo1") - .withId("Conversation1")); - } - } - - public Queue activeQueue() { - return botReplies; - } - - public TestAdapter Use(Middleware middleware) { - super.Use(middleware); - return this; - } - - public void ProcessActivity(ActivityImpl activity, - Consumer callback - ) throws Exception { - synchronized (this.conversationReference()) { - // ready for next reply - if (activity.type() == null) - activity.withType(ActivityTypes.MESSAGE); - activity.withChannelId(this.conversationReference().channelId()); - activity.withFrom(this.conversationReference().user()); - activity.withRecipient(this.conversationReference().bot()); - activity.withConversation(this.conversationReference().conversation()); - activity.withServiceUrl(this.conversationReference().serviceUrl()); - Integer next = this.nextId++; - activity.withId(next.toString()); - } - // Assume Default DateTime : DateTime(0) - if (activity.timestamp() == null || activity.timestamp() == new DateTime(0)) - activity.withTimestamp(DateTime.now()); - - try (TurnContextImpl context = new TurnContextImpl(this, activity)) { - super.RunPipeline(context, callback); - } - return; - } - - public ConversationReference conversationReference() { - return conversationReference; - } - - public void withConversationReference(ConversationReference conversationReference) { - this.conversationReference = conversationReference; - } - - @Override - public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { - List responses = new LinkedList(); - - for (Activity activity : activities) { - if (StringUtils.isEmpty(activity.id())) - activity.withId(UUID.randomUUID().toString()); - - if (activity.timestamp() == null) - activity.withTimestamp(DateTime.now()); - - responses.add(new ResourceResponse().withId(activity.id())); - // This is simulating DELAY - - System.out.println(String.format("TestAdapter:SendActivities(tid:%s):Count:%s", Thread.currentThread().getId(), activities.length)); - for (Activity act : activities) { - System.out.printf(":--------\n: To:%s\n", act.recipient().name()); - System.out.printf(": From:%s\n", (act.from() == null) ? "No from set" : act.from().name()); - System.out.printf(": Text:%s\n:---------", (act.text() == null) ? "No text set" : act.text()); - } - if (activity.type().toString().equals("delay")) { - // The BotFrameworkAdapter and Console adapter implement this - // hack directly in the POST method. Replicating that here - // to keep the behavior as close as possible to facillitate - // more realistic tests. - int delayMs = (int) activity.value(); - Thread.sleep(delayMs); - } else { - synchronized (this.botReplies) { - this.botReplies.add(activity); - } - } - } - return responses.toArray(new ResourceResponse[responses.size()]); - } - - - @Override - public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { - synchronized (this.botReplies) { - List replies = new ArrayList<>(botReplies); - for (int i = 0; i < this.botReplies.size(); i++) { - if (replies.get(i).id().equals(activity.id())) { - replies.set(i, activity); - this.botReplies.clear(); - - for (Activity item : replies) { - this.botReplies.add(item); - } - return new ResourceResponse().withId(activity.id()); - } - } - } - return new ResourceResponse(); - } - - @Override - public void DeleteActivity(TurnContext context, ConversationReference reference) { - synchronized (this.botReplies) { - ArrayList replies = new ArrayList<>(this.botReplies); - for (int i = 0; i < this.botReplies.size(); i++) { - if (replies.get(i).id().equals(reference.activityId())) { - replies.remove(i); - this.botReplies.clear(); - for (Activity item : replies) { - this.botReplies.add(item); - } - break; - } - } - } - return; - } - - /** - * NOTE: this resets the queue, it doesn't actually maintain multiple converstion queues - * - * @param channelId - * @param callback - * @return - */ - //@Override - public CompletableFuture CreateConversation(String channelId, Function callback) { - this.activeQueue().clear(); - MessageActivity update = MessageActivity.CreateConversationUpdateActivity(); - - update.withConversation(new ConversationAccount().withId(UUID.randomUUID().toString())); - TurnContextImpl context = new TurnContextImpl(this, (ActivityImpl) update); - return callback.apply(context); - } - - /** - * Called by TestFlow to check next reply - * - * @return - */ - public Activity GetNextReply() { - synchronized (this.botReplies) { - if (this.botReplies.size() > 0) { - return this.botReplies.remove(); - } - } - return null; - } - - /** - * Called by TestFlow to get appropriate activity for conversationReference of testbot - * - * @param text - * @return - */ - public Activity MakeActivity() { - return MakeActivity(null); - } - - public ActivityImpl MakeActivity(String text) { - Integer next = nextId++; - ActivityImpl activity = (ActivityImpl) new ActivityImpl() - .withType(ActivityTypes.MESSAGE) - .withFrom(conversationReference().user()) - .withRecipient(conversationReference().bot()) - .withConversation(conversationReference().conversation()) - .withServiceUrl(conversationReference().serviceUrl()) - .withId(next.toString()) - .withText(text); - - return activity; - } - - - /** - * Called by TestFlow to send text to the bot - * - * @param userSays - * @return - */ - public void SendTextToBot(String userSays, Consumer callback) throws Exception { - this.ProcessActivity(this.MakeActivity(userSays), callback); - } -} - - +package com.microsoft.bot.builder.adapters; + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import com.microsoft.bot.builder.BotAdapter; +import com.microsoft.bot.builder.Middleware; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.builder.TurnContextImpl; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.*; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; + +public class TestAdapter extends BotAdapter { + private int nextId = 0; + private final Queue botReplies = new LinkedList<>(); + private ConversationReference conversationReference; + + public TestAdapter() { + this(null); + } + + + public TestAdapter(ConversationReference reference) { + if (reference != null) { + this.setConversationReference(reference); + } else { + this.setConversationReference(new ConversationReference() {{ + setChannelId("test"); + setServiceUrl("https://test.com"); + }}); + + this.conversationReference().setUser(new ChannelAccount() {{ + setId("user1"); + setName("User1"); + }}); + this.conversationReference().setBot(new ChannelAccount() {{ + setId("bot"); + setName("Bot"); + }}); + this.conversationReference().setConversation(new ConversationAccount() {{ + setIsGroup(Boolean.FALSE); + setConversationType("convo1"); + setId("Conversation1"); + }}); + } + } + + public Queue activeQueue() { + return botReplies; + } + + public TestAdapter Use(Middleware middleware) { + super.Use(middleware); + return this; + } + + public void ProcessActivity(Activity activity, + Consumer callback + ) throws Exception { + synchronized (this.conversationReference()) { + // ready for next reply + if (activity.getType() == null) + activity.setType(ActivityTypes.MESSAGE); + activity.setChannelId(this.conversationReference().getChannelId()); + activity.setFrom(this.conversationReference().getUser()); + activity.setRecipient(this.conversationReference().getBot()); + activity.setConversation(this.conversationReference().getConversation()); + activity.setServiceUrl(this.conversationReference().getServiceUrl()); + Integer next = this.nextId++; + activity.setId(next.toString()); + } + // Assume Default DateTime : DateTime(0) + if (activity.getTimestamp() == null || activity.getTimestamp() == new DateTime(0)) + activity.setTimestamp(DateTime.now()); + + try (TurnContextImpl context = new TurnContextImpl(this, activity)) { + super.RunPipeline(context, callback); + } + return; + } + + public ConversationReference conversationReference() { + return conversationReference; + } + + public void setConversationReference(ConversationReference conversationReference) { + this.conversationReference = conversationReference; + } + + @Override + public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { + List responses = new LinkedList(); + + for (Activity activity : activities) { + if (StringUtils.isEmpty(activity.getId())) + activity.setId(UUID.randomUUID().toString()); + + if (activity.getTimestamp() == null) + activity.setTimestamp(DateTime.now()); + + responses.add(new ResourceResponse(activity.getId())); + // This is simulating DELAY + + System.out.println(String.format("TestAdapter:SendActivities(tid:%s):Count:%s", Thread.currentThread().getId(), activities.length)); + for (Activity act : activities) { + System.out.printf(":--------\n: To:%s\n", act.getRecipient().getName()); + System.out.printf(": From:%s\n", (act.getFrom() == null) ? "No from set" : act.getFrom().getName()); + System.out.printf(": Text:%s\n:---------", (act.getText() == null) ? "No text set" : act.getText()); + } + if (activity.getType().toString().equals("delay")) { + // The BotFrameworkAdapter and Console adapter implement this + // hack directly in the POST method. Replicating that here + // to keep the behavior as close as possible to facillitate + // more realistic tests. + int delayMs = (int) activity.getValue(); + Thread.sleep(delayMs); + } else { + synchronized (this.botReplies) { + this.botReplies.add(activity); + } + } + } + return responses.toArray(new ResourceResponse[responses.size()]); + } + + + @Override + public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { + synchronized (this.botReplies) { + List replies = new ArrayList<>(botReplies); + for (int i = 0; i < this.botReplies.size(); i++) { + if (replies.get(i).getId().equals(activity.getId())) { + replies.set(i, activity); + this.botReplies.clear(); + + for (Activity item : replies) { + this.botReplies.add(item); + } + return new ResourceResponse(activity.getId()); + } + } + } + return new ResourceResponse(); + } + + @Override + public void DeleteActivity(TurnContext context, ConversationReference reference) { + synchronized (this.botReplies) { + ArrayList replies = new ArrayList<>(this.botReplies); + for (int i = 0; i < this.botReplies.size(); i++) { + if (replies.get(i).getId().equals(reference.getActivityId())) { + replies.remove(i); + this.botReplies.clear(); + for (Activity item : replies) { + this.botReplies.add(item); + } + break; + } + } + } + return; + } + + /** + * NOTE: this resets the queue, it doesn't actually maintain multiple converstion queues + * + * @param channelId + * @param callback + * @return + */ + //@Override + public CompletableFuture CreateConversation(String channelId, Function callback) { + this.activeQueue().clear(); + Activity update = Activity.createConversationUpdateActivity(); + + update.setConversation(new ConversationAccount(UUID.randomUUID().toString())); + TurnContextImpl context = new TurnContextImpl(this, update); + return callback.apply(context); + } + + /** + * Called by TestFlow to check next reply + * + * @return + */ + public Activity GetNextReply() { + synchronized (this.botReplies) { + if (this.botReplies.size() > 0) { + return this.botReplies.remove(); + } + } + return null; + } + + /** + * Called by TestFlow to get appropriate activity for conversationReference of testbot + * + * @return + */ + public Activity MakeActivity() { + return MakeActivity(null); + } + + public Activity MakeActivity(String withText) { + Integer next = nextId++; + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setFrom(conversationReference().getUser()); + setRecipient(conversationReference().getBot()); + setConversation(conversationReference().getConversation()); + setServiceUrl(conversationReference().getServiceUrl()); + setId(next.toString()); + setText(withText); + }}; + + return activity; + } + + + /** + * Called by TestFlow to send text to the bot + * + * @param userSays + * @return + */ + public void SendTextToBot(String userSays, Consumer callback) throws Exception { + this.ProcessActivity(this.MakeActivity(userSays), callback); + } +} + + diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java index e56b74c28..d64b69152 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java @@ -1,57 +1,57 @@ -package com.microsoft.bot.builder.dialogs; - -import com.microsoft.bot.schema.models.AttachmentLayoutTypes; -import com.microsoft.bot.schema.models.TextFormatTypes; - -/** - * Optional message properties that can be sent {@link Extensions.SayAsync(BotToUser, String MessageOptions,)} - */ -public class MessageOptions -{ - public MessageOptions() - { - this.setTextFormat(TextFormatTypes.MARKDOWN.toString()); - this.setAttachmentLayout(AttachmentLayoutTypes.LIST.toString()); - // this.Attachments = new ArrayList(); - // this.Entities = new ArrayList(); - } - - /** - * Indicates whether the bot is accepting, expecting, or ignoring input - */ - //public string InputHint { get; set; } - - /** - * Format of text fields [plain|markdown] Default:markdown - */ - String textFormat; - public String getTextFormat() { - return this.textFormat; - } - public void setTextFormat(String textFormat) { - this.textFormat = textFormat; - } - - - - /** - * Hint for how to deal with multiple attachments: [list|carousel] Default:list - */ - String attachmentLayout; - public String getAttachmentLayout() { - return this.attachmentLayout; - } - public void setAttachmentLayout(String attachmentLayout) { - this.attachmentLayout = attachmentLayout; - } - - /** - * Attachments - */ - //public IList Attachments { get; set; } - - /** - * Collection of Entity objects, each of which contains metadata about this activity. Each Entity object is typed. - */ - //public IList Entities { get; set; } -} +package com.microsoft.bot.builder.dialogs; + +import com.microsoft.bot.schema.AttachmentLayoutTypes; +import com.microsoft.bot.schema.TextFormatTypes; + +/** + * Optional message properties that can be sent {@link Extensions.SayAsync(BotToUser, String MessageOptions,)} + */ +public class MessageOptions +{ + public MessageOptions() + { + this.setTextFormat(TextFormatTypes.MARKDOWN.toString()); + this.setAttachmentLayout(AttachmentLayoutTypes.LIST.toString()); + // this.Attachments = new ArrayList(); + // this.Entities = new ArrayList(); + } + + /** + * Indicates whether the bot is accepting, expecting, or ignoring input + */ + //public string InputHint { get; set; } + + /** + * Format of text fields [plain|markdown] Default:markdown + */ + String textFormat; + public String getTextFormat() { + return this.textFormat; + } + public void setTextFormat(String textFormat) { + this.textFormat = textFormat; + } + + + + /** + * Hint for how to deal with multiple attachments: [list|carousel] Default:list + */ + String attachmentLayout; + public String getAttachmentLayout() { + return this.attachmentLayout; + } + public void setAttachmentLayout(String attachmentLayout) { + this.attachmentLayout = attachmentLayout; + } + + /** + * Attachments + */ + //public IList Attachments { get; set; } + + /** + * Collection of Entity objects, each of which contains metadata about this activity. Each Entity object is typed. + */ + //public IList Entities { get; set; } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/inspection/InspectionActivityExtensions.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/inspection/InspectionActivityExtensions.java new file mode 100644 index 000000000..475926581 --- /dev/null +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/inspection/InspectionActivityExtensions.java @@ -0,0 +1,4 @@ +package com.microsoft.bot.builder.inspection; + +public class InspectionActivityExtensions { +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java index 92ab0f557..ba6f9cfd2 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java @@ -1,43 +1,43 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -package com.microsoft.bot.builder.prompts; - -import com.microsoft.bot.schema.models.CardAction; - -import java.util.ArrayList; - -public class Choice -{ - /** - * Value to return when selected. - */ - String _value; - public void setValue(String value) { - this._value = value; - } - public String getValue() { - return this._value; - } - - /** - * (Optional) action to use when rendering the choice as a suggested action. - */ - CardAction _action; - public CardAction getAction() { - return this._action; - } - public void setAction(CardAction action) { - this._action = action; - } - - /** - * (Optional) list of synonyms to recognize in addition to the value. - */ - ArrayList _synonyms; - public ArrayList getSynonyms() { - return _synonyms; - } - public void setSynonyms(ArrayList synonyms) { - this._synonyms = synonyms; - } -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.bot.builder.prompts; + +import com.microsoft.bot.schema.CardAction; + +import java.util.ArrayList; + +public class Choice +{ + /** + * Value to return when selected. + */ + String _value; + public void setValue(String value) { + this._value = value; + } + public String getValue() { + return this._value; + } + + /** + * (Optional) action to use when rendering the choice as a suggested action. + */ + CardAction _action; + public CardAction getAction() { + return this._action; + } + public void setAction(CardAction action) { + this._action = action; + } + + /** + * (Optional) list of synonyms to recognize in addition to the value. + */ + ArrayList _synonyms; + public ArrayList getSynonyms() { + return _synonyms; + } + public void setSynonyms(ArrayList synonyms) { + this._synonyms = synonyms; + } +} diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotFrameworkAdapterTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotFrameworkAdapterTest.java index 1fe82f7c8..e02b3d5ec 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotFrameworkAdapterTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotFrameworkAdapterTest.java @@ -1,42 +1,44 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.*; -import org.junit.Assert; -import org.junit.Test; - -import java.util.UUID; -import java.util.function.Consumer; - -public class BotFrameworkAdapterTest { - @Test - public void AdapterSingleUse() - { - SimpleAdapter a = new SimpleAdapter(); - a.Use(new CallCountingMiddleware()); - } - - @Test - public void AdapterUseChaining() - { - SimpleAdapter a = new SimpleAdapter(); - a.Use(new CallCountingMiddleware()).Use(new CallCountingMiddleware()); - } - - @Test - public void PassResourceResponsesThrough() throws Exception { - Consumer validateResponse = (activities) -> { - // no need to do anything. - }; - - SimpleAdapter a = new SimpleAdapter(validateResponse); - TurnContextImpl c = new TurnContextImpl(a, new ActivityImpl()); - - String activityId = UUID.randomUUID().toString(); - ActivityImpl activity = TestMessage.Message() - .withId(activityId); - - ResourceResponse resourceResponse = c.SendActivity(activity); - Assert.assertTrue("Incorrect response Id returned", resourceResponse.id() == activityId); - } -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ResourceResponse; +import com.microsoft.bot.schema.*; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.UUID; +import java.util.function.Consumer; + +public class BotFrameworkAdapterTest { + @Test + public void AdapterSingleUse() + { + SimpleAdapter a = new SimpleAdapter(); + a.Use(new CallCountingMiddleware()); + } + + @Test + public void AdapterUseChaining() + { + SimpleAdapter a = new SimpleAdapter(); + a.Use(new CallCountingMiddleware()).Use(new CallCountingMiddleware()); + } + + @Test + public void PassResourceResponsesThrough() throws Exception { + Consumer validateResponse = (activities) -> { + // no need to do anything. + }; + + SimpleAdapter a = new SimpleAdapter(validateResponse); + TurnContextImpl c = new TurnContextImpl(a, new Activity(ActivityTypes.MESSAGE)); + + String activityId = UUID.randomUUID().toString(); + Activity activity = TestMessage.Message(); + activity.setId(activityId); + + ResourceResponse resourceResponse = c.SendActivity(activity); + Assert.assertTrue("Incorrect response Id returned", StringUtils.equals(resourceResponse.getId(), activityId)); + } +} diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java index d344ec620..3a1b09d44 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/BotStateTest.java @@ -10,8 +10,8 @@ import com.microsoft.bot.builder.adapters.TestAdapter; import com.microsoft.bot.builder.adapters.TestFlow; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ResourceResponse; +import com.microsoft.bot.schema.ChannelAccount; +import com.microsoft.bot.schema.ResourceResponse; import com.microsoft.rest.RestClient; import org.apache.commons.lang3.StringUtils; import org.junit.Assert; @@ -33,9 +33,8 @@ public class BotStateTest { protected void initializeClients(RestClient restClient, String botId, String userId) { connector = new RestConnectorClient(restClient); - bot = new ChannelAccount().withId(botId); - user = new ChannelAccount().withId(userId); - + bot = new ChannelAccount(botId); + user = new ChannelAccount(userId); } @@ -67,7 +66,7 @@ public void State_RememberIStoreItemUserState() throws ExecutionException, Inter System.out.flush(); TestState userState = StateTurnContextExtensions.GetUserState(context); Assert.assertNotNull("user state should exist", userState); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": userState.withValue("test"); try { @@ -107,7 +106,7 @@ public void State_RememberPocoUserState() throws ExecutionException, Interrupted TestPocoState userState = StateTurnContextExtensions.GetUserState(context); Assert.assertNotNull("user state should exist", userState); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": userState.setValue("test"); try { @@ -142,7 +141,7 @@ public void State_RememberIStoreItemConversationState() throws ExecutionExceptio { TestState conversationState = StateTurnContextExtensions.GetConversationState(context); Assert.assertNotNull("state.conversation should exist", conversationState); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": conversationState.withValue("test"); try { @@ -177,7 +176,7 @@ public void State_RememberPocoConversationState() throws ExecutionException, Int { TestPocoState conversationState = StateTurnContextExtensions.GetConversationState(context); Assert.assertNotNull("state.conversation should exist", conversationState); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": conversationState.setValue("test"); try { @@ -215,7 +214,7 @@ public void State_CustomStateManagerTest() throws ExecutionException, Interrupte { CustomState customState = CustomKeyState.Get(context); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": customState.setCustomString(testGuid); try { @@ -247,13 +246,13 @@ public void State_RoundTripTypedObjectwTrace() throws ExecutionException, Interr new TestFlow(adapter, (context) -> { - System.out.println(String.format(">>Test Callback(tid:%s): STARTING : %s", Thread.currentThread().getId(), context.getActivity().text())); + System.out.println(String.format(">>Test Callback(tid:%s): STARTING : %s", Thread.currentThread().getId(), context.getActivity().getText())); System.out.flush(); TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); Assert.assertNotNull("conversationstate should exist", conversation); - System.out.println(String.format(">>Test Callback(tid:%s): Text is : %s", Thread.currentThread().getId(), context.getActivity().text())); + System.out.println(String.format(">>Test Callback(tid:%s): Text is : %s", Thread.currentThread().getId(), context.getActivity().getText())); System.out.flush(); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": conversation.withName("test"); try { @@ -262,7 +261,7 @@ public void State_RoundTripTypedObjectwTrace() throws ExecutionException, Interr System.out.flush(); ResourceResponse response = context.SendActivity("value saved"); System.out.println(String.format(">>Test Callback(tid:%s): Response Id: %s", Thread.currentThread().getId(), - response.id())); + response.getId())); System.out.flush(); } catch (Exception e) { @@ -300,7 +299,7 @@ public void State_RoundTripTypedObject() throws ExecutionException, InterruptedE { TypedObject conversation = StateTurnContextExtensions.GetConversationState(context); Assert.assertNotNull("conversationstate should exist", conversation); - switch (context.getActivity().text()) { + switch (context.getActivity().getText()) { case "set value": conversation.withName("test"); try { @@ -335,7 +334,7 @@ public void State_UseBotStateDirectly() throws ExecutionException, InterruptedEx { BotState botStateManager = new BotState(new MemoryStorage(), "BotState:com.microsoft.bot.builder.core.extensions.BotState", (ctx) -> String.format("botstate/%s/%s/com.microsoft.bot.builder.core.extensions.BotState", - ctx.getActivity().channelId(), ctx.getActivity().conversation().id()), CustomState::new); + ctx.getActivity().getChannelId(), ctx.getActivity().getConversation().getId()), CustomState::new); // read initial state object CustomState customState = null; diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java index 9c29fbe77..11e440c5e 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/CatchException_MiddlewareTest.java @@ -3,8 +3,7 @@ import com.microsoft.bot.builder.adapters.TestAdapter; import com.microsoft.bot.builder.adapters.TestFlow; import com.microsoft.bot.connector.ExecutorFactory; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.Activity; import org.junit.Assert; import org.junit.Test; @@ -22,9 +21,9 @@ public void CatchException_TestMiddleware_TestStackedErrorMiddleware() throws Ex public CompletableFuture apply(TurnContext context, T t) throws Exception { return CompletableFuture.runAsync(() -> { Activity activity = context.getActivity(); - if (activity instanceof ActivityImpl) { + if (activity instanceof Activity) { try { - context.SendActivity(((ActivityImpl) activity).CreateReply(t.toString())); + context.SendActivity(((Activity) activity).createReply(t.toString())); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(String.format("CatchException_TestMiddleware_TestStackedErrorMiddleware:SendActivity failed %s", e.toString())); @@ -49,14 +48,14 @@ public CompletableFuture apply(TurnContext context, T t) throws Exception { new TestFlow(adapter, (context) -> { - if (context.getActivity().text() == "foo") { + if (context.getActivity().getText() == "foo") { try { - context.SendActivity(context.getActivity().text()); + context.SendActivity(context.getActivity().getText()); } catch (Exception e) { e.printStackTrace(); } } - if (context.getActivity().text() == "UnsupportedOperationException") { + if (context.getActivity().getText() == "UnsupportedOperationException") { throw new UnsupportedOperationException("Test"); } diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java index a4083f993..73b7eb186 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/MiddlewareSetTest.java @@ -3,7 +3,7 @@ import com.microsoft.bot.builder.base.TestBase; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.ChannelAccount; +import com.microsoft.bot.schema.ChannelAccount; import com.microsoft.rest.RestClient; import org.junit.Assert; import org.junit.Test; @@ -28,8 +28,8 @@ public MiddlewareSetTest() { protected void initializeClients(RestClient restClient, String botId, String userId) { connector = new RestConnectorClient(restClient); - bot = new ChannelAccount().withId(botId); - user = new ChannelAccount().withId(userId); + bot = new ChannelAccount(botId); + user = new ChannelAccount(userId); // Test-specific stuff innerOnreceiveCalled = false; diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/SimpleAdapter.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/SimpleAdapter.java index d2c339f39..07880abb3 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/SimpleAdapter.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/SimpleAdapter.java @@ -1,90 +1,83 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.ResourceResponse; -import org.junit.Assert; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; - -public class SimpleAdapter extends BotAdapter { - private Consumer callOnSend = null; - private Consumer callOnUpdate = null; - private Consumer callOnDelete = null; - - // Callback Function but doesn't need to be. Avoid java legacy type erasure - public SimpleAdapter(Consumer callOnSend) { - this(callOnSend, null, null); - } - - public SimpleAdapter(Consumer callOnSend, Consumer callOnUpdate) { - this(callOnSend, callOnUpdate, null); - } - - public SimpleAdapter(Consumer callOnSend, Consumer callOnUpdate, Consumer callOnDelete) { - this.callOnSend = callOnSend; - this.callOnUpdate = callOnUpdate; - this.callOnDelete = callOnDelete; - } - - public SimpleAdapter() { - - } - - - @Override - public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { - Assert.assertNotNull("SimpleAdapter.deleteActivity: missing reference", activities); - Assert.assertTrue("SimpleAdapter.sendActivities: empty activities array.", activities.length > 0); - - if (this.callOnSend != null) - this.callOnSend.accept(activities); - - List responses = new ArrayList(); - for (Activity activity : activities) { - responses.add(new ResourceResponse().withId(activity.id())); - } - ResourceResponse[] result = new ResourceResponse[responses.size()]; - return responses.toArray(result); - - - } - - @Override - public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { - - Assert.assertNotNull("SimpleAdapter.updateActivity: missing activity", activity); - if (this.callOnUpdate != null) - this.callOnUpdate.accept(activity); - return new ResourceResponse() - .withId(activity.id()); - - - } - - @Override - public void DeleteActivity(TurnContext context, ConversationReference reference) throws ExecutionException, InterruptedException { - Assert.assertNotNull("SimpleAdapter.deleteActivity: missing reference", reference); - if (callOnDelete != null) - this.callOnDelete.accept(reference); - - - } - - - public void ProcessRequest(ActivityImpl activty, Consumer callback) throws Exception { - - try (TurnContextImpl ctx = new TurnContextImpl(this, activty)) { - this.RunPipeline(ctx, callback); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Error running pipeline: %s", e.toString())); - } - - } -} - +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ConversationReference; +import com.microsoft.bot.schema.ResourceResponse; +import org.junit.Assert; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; + +public class SimpleAdapter extends BotAdapter { + private Consumer callOnSend = null; + private Consumer callOnUpdate = null; + private Consumer callOnDelete = null; + + // Callback Function but doesn't need to be. Avoid java legacy type erasure + public SimpleAdapter(Consumer callOnSend) { + this(callOnSend, null, null); + } + + public SimpleAdapter(Consumer callOnSend, Consumer callOnUpdate) { + this(callOnSend, callOnUpdate, null); + } + + public SimpleAdapter(Consumer callOnSend, Consumer callOnUpdate, Consumer callOnDelete) { + this.callOnSend = callOnSend; + this.callOnUpdate = callOnUpdate; + this.callOnDelete = callOnDelete; + } + + public SimpleAdapter() { + + } + + + @Override + public ResourceResponse[] SendActivities(TurnContext context, Activity[] activities) throws InterruptedException { + Assert.assertNotNull("SimpleAdapter.deleteActivity: missing reference", activities); + Assert.assertTrue("SimpleAdapter.sendActivities: empty activities array.", activities.length > 0); + + if (this.callOnSend != null) + this.callOnSend.accept(activities); + + List responses = new ArrayList(); + for (Activity activity : activities) { + responses.add(new ResourceResponse(activity.getId())); + } + ResourceResponse[] result = new ResourceResponse[responses.size()]; + return responses.toArray(result); + + + } + + @Override + public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { + Assert.assertNotNull("SimpleAdapter.updateActivity: missing activity", activity); + if (this.callOnUpdate != null) + this.callOnUpdate.accept(activity); + return new ResourceResponse(activity.getId()); + } + + @Override + public void DeleteActivity(TurnContext context, ConversationReference reference) throws ExecutionException, InterruptedException { + Assert.assertNotNull("SimpleAdapter.deleteActivity: missing reference", reference); + if (callOnDelete != null) + this.callOnDelete.accept(reference); + } + + + public void ProcessRequest(Activity activty, Consumer callback) throws Exception { + + try (TurnContextImpl ctx = new TurnContextImpl(this, activty)) { + this.RunPipeline(ctx, callback); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Error running pipeline: %s", e.toString())); + } + + } +} + diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TestMessage.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TestMessage.java index 94f3fb0ea..231cc7fd5 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TestMessage.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TestMessage.java @@ -1,32 +1,29 @@ -package com.microsoft.bot.builder; - -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.ActivityTypes; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ConversationAccount; - -public class TestMessage { - public static ActivityImpl Message() { - return TestMessage.Message("1234"); - } - - public static ActivityImpl Message(String id) { - ActivityImpl a = new ActivityImpl() - .withType(ActivityTypes.MESSAGE) - .withId(id) - .withText("test") - .withFrom(new ChannelAccount() - .withId("user") - .withName("User Name")) - .withRecipient(new ChannelAccount() - .withId("bot") - .withName("Bot Name")) - .withConversation(new ConversationAccount() - .withId("convo") - .withName("Convo Name")) - .withChannelId("UnitTest") - .withServiceUrl("https://example.org"); - return a; - } - -} +package com.microsoft.bot.builder; + +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; +import com.microsoft.bot.schema.ChannelAccount; +import com.microsoft.bot.schema.ConversationAccount; + +public class TestMessage { + public static Activity Message() { + return TestMessage.Message("1234"); + } + + public static Activity Message(String id) { + Activity a = new Activity(ActivityTypes.MESSAGE) {{ + setId(id); + setText("test"); + setFrom(new ChannelAccount("user", "User Name")); + setRecipient(new ChannelAccount("bot", "Bot Name")); + setConversation(new ConversationAccount() {{ + setId("convo"); + setName("Convo Name"); + }}); + setChannelId("UnitTest"); + setServiceUrl("https://example.org"); + }}; + return a; + } + +} diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java index aad6e6840..523ef21a0 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java @@ -1,263 +1,263 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.builder; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.joda.JodaModule; -import com.microsoft.bot.builder.adapters.TestAdapter; -import com.microsoft.bot.builder.adapters.TestFlow; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.*; -import org.apache.commons.lang3.StringUtils; -import org.junit.Assert; -import org.junit.Test; - -import java.util.concurrent.ExecutionException; - - -public class TranscriptMiddlewareTest { - - @Test - public final void Transcript_SimpleReceive() throws Exception { - MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); - TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); - final String[] conversationId = {null}; - - - new TestFlow(adapter, (ctxt) -> - { - - TurnContextImpl context = (TurnContextImpl) ctxt; - conversationId[0] = context.getActivity().conversation().id(); - ActivityImpl typingActivity = new ActivityImpl() - .withType(ActivityTypes.TYPING) - .withRelatesTo(context.getActivity().relatesTo()); - try { - ResourceResponse response = context.SendActivity(typingActivity); - System.out.printf("Here's the response:"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - Assert.fail(); - } - try { - context.SendActivity("echo:" + context.getActivity().text()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - - }).Send("foo") - .AssertReply((activity) -> { - Assert.assertEquals(activity.type(), ActivityTypes.TYPING); - return null; - }).StartTest(); - //.AssertReply("echo:foo").StartTest(); - - - } - - @Test - public final void Transcript_MiddlewareTest() throws Exception { - MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); - TranscriptLoggerMiddleware logger = new TranscriptLoggerMiddleware(transcriptStore); - TestAdapter adapter = new TestAdapter(); - ActivityImpl activity = ActivityImpl.CreateMessageActivity() - .withFrom(new ChannelAccount().withName("MyAccount").withId("acctid").withRole(RoleTypes.USER)); - TurnContextImpl context = new TurnContextImpl(adapter, activity); - NextDelegate nd = new NextDelegate() { - @Override - public void next() throws Exception { - System.out.printf("Delegate called!"); - System.out.flush(); - return ; - } - }; - ActivityImpl typingActivity = new ActivityImpl() - .withType(ActivityTypes.TYPING) - .withRelatesTo(context.getActivity().relatesTo()); - try { - context.SendActivity(typingActivity); - System.out.printf("HI"); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - - - //logger.OnTurn(context, nd).get(); - } - - @Test - public final void Transcript_LogActivities() throws ExecutionException, InterruptedException { - MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); - TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); - final String[] conversationId = {null}; - - - String result = new TestFlow(adapter, (context) -> - { - - //TurnContextImpl context = (TurnContextImpl) ctxt; - conversationId[0] = context.getActivity().conversation().id(); - ActivityImpl typingActivity = new ActivityImpl() - .withType(ActivityTypes.TYPING) - .withRelatesTo(context.getActivity().relatesTo()); - try { - context.SendActivity((Activity)typingActivity); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - Assert.fail(); - } - try { - context.SendActivity("echo:" + context.getActivity().text()); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - }).Send("foo") - .AssertReply((activity) -> { - Assert.assertEquals(activity.type(), ActivityTypes.TYPING); - return null; - }) - .AssertReply("echo:foo") - .Send("bar") - .AssertReply((activity) -> { - Assert.assertEquals(activity.type(), ActivityTypes.TYPING); - return null; - }) - .AssertReply("echo:bar") - .StartTest(); - - - PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); - Assert.assertEquals(6, pagedResult.getItems().length); - Assert.assertEquals( "foo", ((Activity)pagedResult.getItems()[0]).text()); - Assert.assertNotEquals(((Activity)pagedResult.getItems()[1]), null); - Assert.assertEquals("echo:foo", ((Activity) pagedResult.getItems()[2]).text()); - Assert.assertEquals("bar", ((Activity)pagedResult.getItems()[3]).text()); - - Assert.assertTrue(pagedResult.getItems()[4] != null); - Assert.assertEquals("echo:bar", ((Activity)pagedResult.getItems()[5]).text()); - for (Object activity : pagedResult.getItems()) - { - Assert.assertFalse(StringUtils.isBlank(((Activity) activity).id())); - Assert.assertTrue(((Activity)activity).timestamp().isAfter(Long.MIN_VALUE)); - } - System.out.printf("Complete"); - } - - @Test - public void Transcript_LogUpdateActivities() throws InterruptedException, ExecutionException { - MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); - TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); - final String[] conversationId = {null}; - final Activity[] activityToUpdate = {null}; - ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JodaModule()); - new TestFlow(adapter, (context) -> - { - - conversationId[0] = context.getActivity().conversation().id(); - if (context.getActivity().text().equals("update")) { - activityToUpdate[0].withText("new response"); - try { - context.UpdateActivity(activityToUpdate[0]); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - ActivityImpl activity = ((ActivityImpl) context.getActivity()).CreateReply("response"); - ResourceResponse response = null; - try { - response = context.SendActivity(activity); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - activity.withId(response.id()); - - // clone the activity, so we can use it to do an update - activityToUpdate[0] = ActivityImpl.CloneActity(activity); - //JsonConvert.DeserializeObject(JsonConvert.SerializeObject(activity)); - } - }).Send("foo") - .Send("update") - .AssertReply("new response") - .StartTest(); - Thread.sleep(500); - PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); - Assert.assertEquals(4, pagedResult.getItems().length); - Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).text()); - Assert.assertEquals( "response", ((Activity)pagedResult.getItems()[1]).text()); - // TODO: Fix the following 3 asserts so they work correctly. They succeed in the travis builds and fail in the - // BotBuilder-Java 4.0 master build. - //Assert.assertEquals( "new response", ((Activity)pagedResult.getItems()[2]).text()); - //Assert.assertEquals("update", ((Activity)pagedResult.getItems()[3]).text()); - //Assert.assertEquals( ((Activity)pagedResult.getItems()[1]).id(), ((Activity) pagedResult.getItems()[2]).id()); - } - - @Test - public final void Transcript_LogDeleteActivities() throws InterruptedException, ExecutionException { - MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); - TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); - final String[] conversationId = {null}; - final String[] activityId = {null}; - new TestFlow(adapter, (context) -> - { - - conversationId[0] = context.getActivity().conversation().id(); - if (context.getActivity().text().equals("deleteIt")) { - try { - context.DeleteActivity(activityId[0]).join(); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - } else { - ActivityImpl activity = ((ActivityImpl) context.getActivity()).CreateReply("response"); - ResourceResponse response = null; - try { - response = context.SendActivity(activity); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - activityId[0] = response.id(); - } - - - }).Send("foo") - .AssertReply("response") - .Send("deleteIt") - .StartTest(); - Thread.sleep(1500); - PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); - for (Object act : pagedResult.getItems()) { - System.out.printf("Here is the object: %s : Type: %s\n", act.getClass().getTypeName(), ((Activity)act).type()); - } - - for (Object activity : pagedResult.getItems() ) { - System.out.printf("Recipient: %s\nText: %s\n", ((Activity) activity).recipient().name(), ((Activity)activity).text()); - } - Assert.assertEquals(4, pagedResult.getItems().length); - Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).text()); - Assert.assertEquals("response", ((Activity)pagedResult.getItems()[1]).text()); - Assert.assertEquals("deleteIt", ((Activity)pagedResult.getItems()[2]).text()); - Assert.assertEquals(ActivityTypes.MESSAGE_DELETE, ((Activity)pagedResult.getItems()[3]).type()); - Assert.assertEquals(((Activity)pagedResult.getItems()[1]).id(), ((Activity) pagedResult.getItems()[3]).id()); - } -} - +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.builder; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; +import com.microsoft.bot.builder.adapters.TestAdapter; +import com.microsoft.bot.builder.adapters.TestFlow; +import com.microsoft.bot.schema.*; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.ExecutionException; + + +public class TranscriptMiddlewareTest { + + @Test + public final void Transcript_SimpleReceive() throws Exception { + MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); + TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); + final String[] conversationId = {null}; + + + new TestFlow(adapter, (ctxt) -> + { + + TurnContextImpl context = (TurnContextImpl) ctxt; + conversationId[0] = context.getActivity().getConversation().getId(); + Activity typingActivity = new Activity(ActivityTypes.TYPING) {{ + setRelatesTo(context.getActivity().getRelatesTo()); + }}; + try { + ResourceResponse response = context.SendActivity(typingActivity); + System.out.printf("Here's the response:"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + Assert.fail(); + } + try { + context.SendActivity("echo:" + context.getActivity().getText()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + + }).Send("foo") + .AssertReply((activity) -> { + Assert.assertEquals(activity.getType(), ActivityTypes.TYPING); + return null; + }).StartTest(); + //.AssertReply("echo:foo").StartTest(); + + + } + + @Test + public final void Transcript_MiddlewareTest() throws Exception { + MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); + TranscriptLoggerMiddleware logger = new TranscriptLoggerMiddleware(transcriptStore); + TestAdapter adapter = new TestAdapter(); + Activity activity = Activity.createMessageActivity(); + activity.setFrom(new ChannelAccount("acctid", "MyAccount", RoleTypes.USER)); + TurnContextImpl context = new TurnContextImpl(adapter, activity); + NextDelegate nd = new NextDelegate() { + @Override + public void next() throws Exception { + System.out.printf("Delegate called!"); + System.out.flush(); + return ; + } + }; + Activity typingActivity = new Activity(ActivityTypes.TYPING) {{ + setRelatesTo(context.getActivity().getRelatesTo()); + }}; + + try { + context.SendActivity(typingActivity); + System.out.printf("HI"); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + + + //logger.OnTurn(context, nd).get(); + } + + @Test + public final void Transcript_LogActivities() throws ExecutionException, InterruptedException { + MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); + TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); + final String[] conversationId = {null}; + + + String result = new TestFlow(adapter, (context) -> + { + + //TurnContextImpl context = (TurnContextImpl) ctxt; + conversationId[0] = context.getActivity().getConversation().getId(); + Activity typingActivity = new Activity(ActivityTypes.TYPING) {{ + setRelatesTo(context.getActivity().getRelatesTo()); + }}; + try { + context.SendActivity((Activity)typingActivity); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + Assert.fail(); + } + try { + context.SendActivity("echo:" + context.getActivity().getText()); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + }).Send("foo") + .AssertReply((activity) -> { + Assert.assertEquals(activity.getType(), ActivityTypes.TYPING); + return null; + }) + .AssertReply("echo:foo") + .Send("bar") + .AssertReply((activity) -> { + Assert.assertEquals(activity.getType(), ActivityTypes.TYPING); + return null; + }) + .AssertReply("echo:bar") + .StartTest(); + + + PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); + Assert.assertEquals(6, pagedResult.getItems().length); + Assert.assertEquals( "foo", ((Activity)pagedResult.getItems()[0]).getText()); + Assert.assertNotEquals(((Activity)pagedResult.getItems()[1]), null); + Assert.assertEquals("echo:foo", ((Activity) pagedResult.getItems()[2]).getText()); + Assert.assertEquals("bar", ((Activity)pagedResult.getItems()[3]).getText()); + + Assert.assertTrue(pagedResult.getItems()[4] != null); + Assert.assertEquals("echo:bar", ((Activity)pagedResult.getItems()[5]).getText()); + for (Object activity : pagedResult.getItems()) + { + Assert.assertFalse(StringUtils.isBlank(((Activity) activity).getId())); + Assert.assertTrue(((Activity)activity).getTimestamp().isAfter(Long.MIN_VALUE)); + } + System.out.printf("Complete"); + } + + @Test + public void Transcript_LogUpdateActivities() throws InterruptedException, ExecutionException { + MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); + TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); + final String[] conversationId = {null}; + final Activity[] activityToUpdate = {null}; + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new JodaModule()); + new TestFlow(adapter, (context) -> + { + + conversationId[0] = context.getActivity().getConversation().getId(); + if (context.getActivity().getText().equals("update")) { + activityToUpdate[0].setText("new response"); + try { + context.UpdateActivity(activityToUpdate[0]); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + Activity activity = ((Activity) context.getActivity()).createReply("response"); + ResourceResponse response = null; + try { + response = context.SendActivity(activity); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + activity.setId(response.getId()); + + // clone the activity, so we can use it to do an update + activityToUpdate[0] = Activity.cloneActivity(activity); + //JsonConvert.DeserializeObject(JsonConvert.SerializeObject(activity)); + } + }).Send("foo") + .Send("update") + .AssertReply("new response") + .StartTest(); + Thread.sleep(500); + PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); + Assert.assertEquals(4, pagedResult.getItems().length); + Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).getText()); + Assert.assertEquals( "response", ((Activity)pagedResult.getItems()[1]).getText()); + // TODO: Fix the following 3 asserts so they work correctly. They succeed in the travis builds and fail in the + // BotBuilder-Java 4.0 master build. + //Assert.assertEquals( "new response", ((Activity)pagedResult.getItems()[2]).text()); + //Assert.assertEquals("update", ((Activity)pagedResult.getItems()[3]).text()); + //Assert.assertEquals( ((Activity)pagedResult.getItems()[1]).getId(), ((Activity) pagedResult.getItems()[2]).getId()); + } + + @Test + public final void Transcript_LogDeleteActivities() throws InterruptedException, ExecutionException { + MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore(); + TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore)); + final String[] conversationId = {null}; + final String[] activityId = {null}; + new TestFlow(adapter, (context) -> + { + + conversationId[0] = context.getActivity().getConversation().getId(); + if (context.getActivity().getText().equals("deleteIt")) { + try { + context.DeleteActivity(activityId[0]).join(); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + } else { + Activity activity = ((Activity) context.getActivity()).createReply("response"); + ResourceResponse response = null; + try { + response = context.SendActivity(activity); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(); + } + activityId[0] = response.getId(); + } + + + }).Send("foo") + .AssertReply("response") + .Send("deleteIt") + .StartTest(); + Thread.sleep(1500); + PagedResult pagedResult = transcriptStore.GetTranscriptActivitiesAsync("test", conversationId[0]).join(); + for (Object act : pagedResult.getItems()) { + System.out.printf("Here is the object: %s : Type: %s\n", act.getClass().getTypeName(), ((Activity)act).getType()); + } + + for (Object activity : pagedResult.getItems() ) { + System.out.printf("Recipient: %s\nText: %s\n", ((Activity) activity).getRecipient().getName(), ((Activity)activity).getText()); + } + Assert.assertEquals(4, pagedResult.getItems().length); + Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).getText()); + Assert.assertEquals("response", ((Activity)pagedResult.getItems()[1]).getText()); + Assert.assertEquals("deleteIt", ((Activity)pagedResult.getItems()[2]).getText()); + Assert.assertEquals(ActivityTypes.MESSAGE_DELETE, ((Activity)pagedResult.getItems()[3]).getType()); + Assert.assertEquals(((Activity)pagedResult.getItems()[1]).getId(), ((Activity) pagedResult.getItems()[3]).getId()); + } +} + diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java index e48a727bd..365deee22 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/adapters/TestFlow.java @@ -2,8 +2,8 @@ import com.microsoft.bot.builder.TurnContext; import com.microsoft.bot.connector.ExecutorFactory; -import com.microsoft.bot.schema.ActivityImpl; -import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.Activity; +import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.junit.Assert; @@ -112,13 +112,13 @@ public TestFlow Send(Activity userActivity) { throw new IllegalArgumentException("You have to pass an Activity"); return new TestFlow((() -> { - System.out.printf("TestFlow(%s): Send with User Activity! %s", Thread.currentThread().getId(), userActivity.text()); + System.out.printf("TestFlow(%s): Send with User Activity! %s", Thread.currentThread().getId(), userActivity.getText()); System.out.flush(); try { - this.adapter.ProcessActivity((ActivityImpl) userActivity, this.callback); - return "TestFlow: Send() -> ProcessActivity: " + userActivity.text(); + this.adapter.ProcessActivity((Activity) userActivity, this.callback); + return "TestFlow: Send() -> ProcessActivity: " + userActivity.getText(); } catch (Exception e) { return e.getMessage(); @@ -151,8 +151,6 @@ public TestFlow Delay(int ms) { * Assert that reply is expected text * * @param expected - * @param description - * @param timeout * @return */ public TestFlow AssertReply(String expected) { @@ -171,8 +169,6 @@ public TestFlow AssertReply(String expected, String description, int timeout) { * Assert that the reply is expected activity * * @param expected - * @param description - * @param timeout * @return */ public TestFlow AssertReply(Activity expected) { @@ -185,11 +181,11 @@ public TestFlow AssertReply(Activity expected, String description, int timeout) description = Thread.currentThread().getStackTrace()[1].getMethodName(); String finalDescription = description; return this.AssertReply((reply) -> { - if (expected.type() != reply.type()) + if (expected.getType() != reply.getType()) return String.format("%s: Type should match", finalDescription); - if (expected.text().equals(reply.text())) { + if (expected.getText().equals(reply.getText())) { if (finalDescription == null) - return String.format("Expected:%s\nReceived:{reply.AsMessageActivity().Text}", expected.text()); + return String.format("Expected:%s\nReceived:{reply.AsMessageActivity().Text}", expected.getText()); else return String.format("%s: Text should match", finalDescription); } @@ -202,8 +198,6 @@ public TestFlow AssertReply(Activity expected, String description, int timeout) * Assert that the reply matches a custom validation routine * * @param validateActivity - * @param description - * @param timeout * @return */ public TestFlow AssertReply(Function validateActivity) { @@ -242,10 +236,10 @@ public TestFlow AssertReply(Function validateActivity, String // System.out.flush(); if (replyActivity != null) { - System.out.printf("AssertReply(tid:%s): Received Reply: %s ", Thread.currentThread().getId(), (replyActivity.text() == null) ? "No Text set" : replyActivity.text()); + System.out.printf("AssertReply(tid:%s): Received Reply: %s ", Thread.currentThread().getId(), (replyActivity.getText() == null) ? "No Text set" : replyActivity.getText()); System.out.flush(); - System.out.printf("=============\n From: %s\n To:%s\n ==========\n", (replyActivity.from() == null) ? "No from set" : replyActivity.from().name(), - (replyActivity.recipient() == null) ? "No recipient set" : replyActivity.recipient().name()); + System.out.printf("=============\n From: %s\n To:%s\n ==========\n", (replyActivity.getFrom() == null) ? "No from set" : replyActivity.getFrom().getName(), + (replyActivity.getRecipient() == null) ? "No recipient set" : replyActivity.getRecipient().getName()); System.out.flush(); // if we have a reply @@ -304,7 +298,7 @@ public TestFlow Turn(String userSays, String expected, String description, int t if (isDebug()) finalTimeout = Integer.MAX_VALUE; Function validateActivity = activity -> { - if (activity.text().equals(expected)) { + if (activity.getText().equals(expected)) { System.out.println(String.format("TestTurn(tid:%s): Validated text is: %s", Thread.currentThread().getId(), expected)); System.out.flush(); @@ -313,7 +307,7 @@ public TestFlow Turn(String userSays, String expected, String description, int t System.out.println(String.format("TestTurn(tid:%s): Failed validate text is: %s", Thread.currentThread().getId(), expected)); System.out.flush(); - return String.format("FAIL: %s received in Activity.text (%s expected)", activity.text(), expected); + return String.format("FAIL: %s received in Activity.text (%s expected)", activity.getText(), expected); }; @@ -334,7 +328,7 @@ public TestFlow Turn(String userSays, String expected, String description, int t // if we have a reply System.out.println(String.format("TestTurn(tid:%s): Received Reply: %s", Thread.currentThread().getId(), - String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.recipient().name(), replyActivity.from().name(), replyActivity.text()) + String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.getRecipient().getName(), replyActivity.getFrom().getName(), replyActivity.getText()) )); System.out.flush(); return validateActivity.apply(replyActivity); @@ -367,8 +361,6 @@ public TestFlow Turn(String userSays, String expected, String description, int t * * @param userSays * @param expected - * @param description - * @param timeout * @return */ public TestFlow Test(String userSays, String expected) { @@ -392,8 +384,6 @@ public TestFlow Test(String userSays, String expected, String description, int t * * @param userSays * @param expected - * @param description - * @param timeout * @return */ public TestFlow Test(String userSays, Activity expected) { @@ -417,8 +407,6 @@ public TestFlow Test(String userSays, Activity expected, String description, int * * @param userSays * @param expected - * @param description - * @param timeout * @return */ public TestFlow Test(String userSays, Function expected) { @@ -441,8 +429,6 @@ public TestFlow Test(String userSays, Function expected, Strin * Assert that reply is one of the candidate responses * * @param candidates - * @param description - * @param timeout * @return */ public TestFlow AssertReplyOneOf(String[] candidates) { @@ -459,7 +445,7 @@ public TestFlow AssertReplyOneOf(String[] candidates, String description, int ti return this.AssertReply((reply) -> { for (String candidate : candidates) { - if (reply.text() == candidate) + if (StringUtils.equals(reply.getText(), candidate)) return null; } return String.format("%s: Not one of candidates: %s", description, String.join("\n ", candidates)); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java index 8c52d36a7..63974dcab 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java @@ -6,7 +6,7 @@ package com.microsoft.bot.connector; -import com.microsoft.bot.schema.models.AttachmentInfo; +import com.microsoft.bot.schema.AttachmentInfo; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java index a07381758..547ac65cd 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java @@ -10,7 +10,7 @@ package com.microsoft.bot.connector; -import com.microsoft.bot.schema.models.*; +import com.microsoft.bot.schema.*; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index 0c4a10546..d7e185c06 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -5,7 +5,7 @@ import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.bot.connector.ExecutorFactory; -import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.Activity; import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; @@ -57,10 +57,10 @@ public static CompletableFuture authenticateRequest(Activity act // Go through the standard authentication path. This will throw AuthenticationException if // it fails. - ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.channelId(), activity.serviceUrl(), authConfig).join(); + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.getChannelId(), activity.getServiceUrl(), authConfig).join(); // On the standard Auth path, we need to trust the URL that was incoming. - MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl()); + MicrosoftAppCredentials.trustServiceUrl(activity.getServiceUrl()); return identity; }, ExecutorFactory.getExecutor()); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java index 3dd10eb28..f3289572a 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OAuthClient.java @@ -8,10 +8,10 @@ import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.UserAgent; import com.microsoft.bot.connector.rest.RestConnectorClient; +import com.microsoft.bot.schema.Activity; import com.microsoft.bot.schema.TokenExchangeState; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.TokenResponse; +import com.microsoft.bot.schema.ConversationReference; +import com.microsoft.bot.schema.TokenResponse; import com.microsoft.rest.ServiceClient; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -241,16 +241,18 @@ public CompletableFuture GetSignInLinkAsync(Activity activity, String co throw new IllegalArgumentException("activity"); } final MicrosoftAppCredentials creds = (MicrosoftAppCredentials) this.client.restClient().credentials(); - TokenExchangeState tokenExchangeState = new TokenExchangeState() - .withConnectionName(connectionName) - .withConversation(new ConversationReference() - .withActivityId(activity.id()) - .withBot(activity.recipient()) - .withChannelId(activity.channelId()) - .withConversation(activity.conversation()) - .withServiceUrl(activity.serviceUrl()) - .withUser(activity.from())) - .withMsAppId((creds == null) ? null : creds.appId()); + TokenExchangeState tokenExchangeState = new TokenExchangeState() {{ + setConnectionName(connectionName); + setConversation(new ConversationReference() {{ + setActivityId(activity.getId()); + setBot(activity.getRecipient()); + setChannelId(activity.getChannelId()); + setConversation(activity.getConversation()); + setServiceUrl(activity.getServiceUrl()); + setUser(activity.getFrom()); + }}); + setMsAppId((creds == null) ? null : creds.appId()); + }}; String serializedState = this.mapper.writeValueAsString(tokenExchangeState); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java index 390c35f13..520d4b90f 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/ErrorResponseException.java @@ -6,7 +6,7 @@ package com.microsoft.bot.connector.rest; -import com.microsoft.rest.RestException;import com.microsoft.bot.schema.models.ErrorResponse; +import com.microsoft.rest.RestException;import com.microsoft.bot.schema.ErrorResponse; import okhttp3.ResponseBody; import retrofit2.Response; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java index 68ba3f111..fa70a3d5d 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java @@ -9,7 +9,7 @@ import retrofit2.Retrofit; import com.microsoft.bot.connector.Attachments; import com.google.common.reflect.TypeToken; -import com.microsoft.bot.schema.models.AttachmentInfo; +import com.microsoft.bot.schema.AttachmentInfo; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java index 40d2d1d96..ee25b26e6 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java @@ -6,18 +6,10 @@ package com.microsoft.bot.connector.rest; +import com.microsoft.bot.schema.*; import retrofit2.Retrofit; import com.microsoft.bot.connector.Conversations; import com.google.common.reflect.TypeToken; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.AttachmentData; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ConversationParameters; -import com.microsoft.bot.schema.models.ConversationResourceResponse; -import com.microsoft.bot.schema.models.ConversationsResult; -import com.microsoft.bot.schema.models.PagedMembersResult; -import com.microsoft.bot.schema.models.ResourceResponse; -import com.microsoft.bot.schema.models.Transcript; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceFuture; import com.microsoft.rest.ServiceResponse; diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java index 8a69ca972..cdb31963b 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java @@ -1,6 +1,6 @@ package com.microsoft.bot.connector; -import com.microsoft.bot.schema.models.*; +import com.microsoft.bot.schema.*; import org.junit.Assert; import org.junit.Test; @@ -13,22 +13,24 @@ public class AttachmentsTest extends BotConnectorTestBase { @Test public void GetAttachmentInfo() { - AttachmentData attachment = new AttachmentData() - .withName("bot-framework.png") - .withType("image/png") - .withOriginalBase64(encodeToBase64(new File(getClass().getClassLoader().getResource("bot-framework.png").getFile()))); + AttachmentData attachment = new AttachmentData() {{ + setName("bot-framework.png"); + setType("image/png"); + setOriginalBase64(encodeToBase64(new File(getClass().getClassLoader().getResource("bot-framework.png").getFile()))); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.id(), attachment); + ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.getId(), attachment); - AttachmentInfo response = connector.attachments().getAttachmentInfo(attachmentResponse.id()); + AttachmentInfo response = connector.attachments().getAttachmentInfo(attachmentResponse.getId()); - Assert.assertEquals(attachment.name(), response.name()); + Assert.assertEquals(attachment.getName(), response.getName()); } @Test @@ -44,23 +46,25 @@ public void GetAttachment() { e.printStackTrace(); } - AttachmentData attachment = new AttachmentData() - .withName("bot_icon.png") - .withType("image/png") - .withOriginalBase64(attachmentPayload); + AttachmentData attachment = new AttachmentData() {{ + setName("bot_icon.png"); + setType("image/png"); + setOriginalBase64(attachmentPayload); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.id(), attachment); + ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.getId(), attachment); - AttachmentInfo attachmentInfo = connector.attachments().getAttachmentInfo(attachmentResponse.id()); + AttachmentInfo attachmentInfo = connector.attachments().getAttachmentInfo(attachmentResponse.getId()); - for (AttachmentView attView : attachmentInfo.views()) { - InputStream retrievedAttachment = connector.attachments().getAttachment(attachmentResponse.id(), attView.viewId()); + for (AttachmentView attView : attachmentInfo.getViews()) { + InputStream retrievedAttachment = connector.attachments().getAttachment(attachmentResponse.getId(), attView.getViewId()); Assert.assertTrue(isSame(retrievedAttachment, attachmentStream)); } @@ -69,7 +73,7 @@ public void GetAttachment() { private byte[] encodeToBase64(File file) { try { FileInputStream fis = new FileInputStream(file); - byte[] result = new byte[(int)file.length()]; + byte[] result = new byte[(int) file.length()]; int size = fis.read(result); return result; } catch (Exception ex) { diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java index e649af8da..09d9b64f3 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/BotConnectorTestBase.java @@ -2,7 +2,7 @@ import com.microsoft.bot.connector.base.TestBase; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.ChannelAccount; +import com.microsoft.bot.schema.ChannelAccount; import com.microsoft.rest.RestClient; public class BotConnectorTestBase extends TestBase { @@ -21,8 +21,8 @@ public BotConnectorTestBase(RunCondition runCondition) { @Override protected void initializeClients(RestClient restClient, String botId, String userId) { connector = new RestConnectorClient(restClient); - bot = new ChannelAccount().withId(botId); - user = new ChannelAccount().withId(userId); + bot = new ChannelAccount(botId); + user = new ChannelAccount(userId); } @Override diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java index 0e5cb6982..3952f67df 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java @@ -4,7 +4,7 @@ package com.microsoft.bot.connector; import com.microsoft.bot.connector.rest.ErrorResponseException; -import com.microsoft.bot.schema.models.*; +import com.microsoft.bot.schema.*; import org.junit.Assert; import org.junit.Test; @@ -19,105 +19,111 @@ public class ConversationsTest extends BotConnectorTestBase { @Test public void CreateConversation() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Create Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Create Conversation"); + }}; - ConversationParameters params = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot) - .withActivity(activity); + ConversationParameters params = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; ConversationResourceResponse result = connector.conversations().createConversation(params); - Assert.assertNotNull(result.activityId()); + Assert.assertNotNull(result.getActivityId()); } @Test public void CreateConversationWithInvalidBot() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Create Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Create Conversation"); + }}; - ConversationParameters params = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot.withId("invalid-id")) - .withActivity(activity); + bot.setId("invalid-id"); + ConversationParameters params = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; try { ConversationResourceResponse result = connector.conversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().startsWith("Invalid userId")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().startsWith("Invalid userId")); } } @Test public void CreateConversationWithoutMembers() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Create Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Create Conversation"); + }}; - ConversationParameters params = new ConversationParameters() - .withMembers(Collections.emptyList()) - .withBot(bot) - .withActivity(activity); + ConversationParameters params = new ConversationParameters() {{ + setMembers(Collections.emptyList()); + setBot(bot); + setActivity(activity); + }}; try { ConversationResourceResponse result = connector.conversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("BadArgument", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().startsWith("Conversations")); + Assert.assertEquals("BadArgument", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().startsWith("Conversations")); } } @Test public void CreateConversationWithBotMember() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Create Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Create Conversation"); + }}; - ConversationParameters params = new ConversationParameters() - .withMembers(Collections.singletonList(bot)) - .withBot(bot) - .withActivity(activity); + ConversationParameters params = new ConversationParameters() {{ + setMembers(Collections.singletonList(bot)); + setBot(bot); + setActivity(activity); + }}; try { ConversationResourceResponse result = connector.conversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("BadArgument", e.body().error().code().toString()); + Assert.assertEquals("BadArgument", e.body().getError().getCode().toString()); } } @Test public void GetConversationMembers() { - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - List members = connector.conversations().getConversationMembers(conversation.id()); + List members = connector.conversations().getConversationMembers(conversation.getId()); boolean hasUser = false; for (ChannelAccount member : members) { - hasUser = member.id().equals(user.id()); + hasUser = member.getId().equals(user.getId()); if (hasUser) break; } @@ -127,176 +133,189 @@ public void GetConversationMembers() { @Test public void GetConversationMembersWithInvalidConversationId() { - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); try { - List members = connector.conversations().getConversationMembers(conversation.id().concat("M")); + List members = connector.conversations().getConversationMembers(conversation.getId().concat("M")); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("The specified channel was not found")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("The specified channel was not found")); } } @Test - public void GetConversationPagedMembers(){ - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + public void GetConversationPagedMembers() { + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); try { - PagedMembersResult pagedMembers = connector.conversations().getConversationPagedMembers(conversation.id()); + PagedMembersResult pagedMembers = connector.conversations().getConversationPagedMembers(conversation.getId()); boolean hasUser = false; - for(ChannelAccount member : pagedMembers.members()){ - hasUser = member.id().equalsIgnoreCase(user.id()); - if(hasUser) + for (ChannelAccount member : pagedMembers.getMembers()) { + hasUser = member.getId().equalsIgnoreCase(user.getId()); + if (hasUser) break; } Assert.assertTrue(hasUser); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); } } @Test public void SendToConversation() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withName("activity") - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setName("activity"); + setText("TEST Send to Conversation"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); - Assert.assertNotNull(response.id()); + Assert.assertNotNull(response.getId()); } @Test public void SendToConversationWithInvalidConversationId() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withName("activity") - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setName("activity"); + setText("TEST Send to Conversation"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); try { - ResourceResponse response = connector.conversations().sendToConversation(conversation.id().concat("M"), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId().concat("M"), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("The specified channel was not found")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("The specified channel was not found")); } } @Test public void SendToConversationWithInvalidBotId() { - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot.withId("B21S8SG7K:T03CWQ0QB")) - .withName("activity") - .withText("TEST Send to Conversation"); + bot.setId("B21S8SG7K:T03CWQ0QB"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setName("activity"); + setText("TEST Send to Conversation"); + }}; try { - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("MissingProperty", e.body().error().code().toString()); - Assert.assertEquals("The bot referenced by the 'from' field is unrecognized", e.body().error().message()); + Assert.assertEquals("MissingProperty", e.body().getError().getCode().toString()); + Assert.assertEquals("The bot referenced by the 'from' field is unrecognized", e.body().getError().getMessage()); } } @Test public void SendCardToConversation() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withName("activity") - .withText("TEST Send Card to Conversation") - .withAttachments(Arrays.asList( - new Attachment() - .withContentType("application/vnd.microsoft.card.hero") - .withContent(new HeroCard() - .withTitle("A static image") - .withSubtitle("JPEG image") - .withImages(Collections.singletonList(new CardImage() - .withUrl("https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/dialogs-screens.png")))), - new Attachment() - .withContentType("application/vnd.microsoft.card.hero") - .withContent(new HeroCard() - .withTitle("An animation") - .withSubtitle("GIF image") - .withImages(Collections.singletonList(new CardImage() - .withUrl("http://i.giphy.com/Ki55RUbOV5njy.gif")))) - - )); - - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setName("activity"); + setText("TEST Send Card to Conversation"); + setAttachments(Arrays.asList( + new Attachment() {{ + setContentType("application/vnd.microsoft.card.hero"); + setContent(new HeroCard() {{ + setTitle("A static image"); + setSubtitle("JPEG image"); + setImages(Collections.singletonList(new CardImage() {{ + setUrl("https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/dialogs-screens.png"); + }})); + }}); + }}, + new Attachment() {{ + setContentType("application/vnd.microsoft.card.hero"); + setContent(new HeroCard() {{ + setTitle("An animation"); + setSubtitle("GIF image"); + setImages(Collections.singletonList(new CardImage() {{ + setUrl("http://i.giphy.com/Ki55RUbOV5njy.gif"); + }})); + }}); + }} + )); + }}; + + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); - Assert.assertNotNull(response.id()); + Assert.assertNotNull(response.getId()); } @Test public void GetActivityMembers() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Get Activity Members"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Get Activity Members"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot) - .withActivity(activity); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - List members = connector.conversations().getActivityMembers(conversation.id(), conversation.activityId()); + List members = connector.conversations().getActivityMembers(conversation.getId(), conversation.getActivityId()); boolean hasUser = false; for (ChannelAccount member : members) { - hasUser = member.id().equals(user.id()); + hasUser = member.getId().equals(user.getId()); if (hasUser) break; } @@ -306,211 +325,220 @@ public void GetActivityMembers() { @Test public void GetActivityMembersWithInvalidConversationId() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Get Activity Members"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Get Activity Members"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot) - .withActivity(activity); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); try { - List members = connector.conversations().getActivityMembers(conversation.id().concat("M"), conversation.activityId()); + List members = connector.conversations().getActivityMembers(conversation.getId().concat("M"), conversation.getActivityId()); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("The specified channel was not found")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("The specified channel was not found")); } } @Test public void ReplyToActivity() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Send to Conversation"); + }}; - Activity reply = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Reply to Activity"); + Activity reply = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Reply to Activity"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); - ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.id(), response.id(), reply); + ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.getId(), response.getId(), reply); - Assert.assertNotNull(replyResponse.id()); + Assert.assertNotNull(replyResponse.getId()); } @Test public void ReplyToActivityWithInvalidConversationId() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Send to Conversation"); + }}; - Activity reply = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Reply to Activity"); + Activity reply = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Reply to Activity"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); try { - ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.id().concat("M"), response.id(), reply); + ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.getId().concat("M"), response.getId(), reply); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("The specified channel was not found")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("The specified channel was not found")); } } @Test public void DeleteActivity() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Delete Activity"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Delete Activity"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot) - .withActivity(activity); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - connector.conversations().deleteActivity(conversation.id(), conversation.activityId()); + connector.conversations().deleteActivity(conversation.getId(), conversation.getActivityId()); - Assert.assertNotNull(conversation.activityId()); + Assert.assertNotNull(conversation.getActivityId()); } @Test public void DeleteActivityWithInvalidConversationId() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Delete Activity"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Delete Activity"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot) - .withActivity(activity); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + setActivity(activity); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); try { - connector.conversations().deleteActivity("B21S8SG7K:T03CWQ0QB", conversation.activityId()); + connector.conversations().deleteActivity("B21S8SG7K:T03CWQ0QB", conversation.getActivityId()); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("Invalid ConversationId")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("Invalid ConversationId")); } } @Test public void UpdateActivity() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Send to Conversation"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); - Activity update = activity.withId(response.id()) - .withText("TEST Update Activity"); + activity.setId(response.getId()); + activity.setText("TEST Update Activity"); - ResourceResponse updateResponse = connector.conversations().updateActivity(conversation.id(), response.id(), update); + ResourceResponse updateResponse = connector.conversations().updateActivity(conversation.getId(), response.getId(), activity); - Assert.assertNotNull(updateResponse.id()); + Assert.assertNotNull(updateResponse.getId()); } @Test public void UpdateActivityWithInvalidConversationId() { - Activity activity = new Activity() - .withType(ActivityTypes.MESSAGE) - .withRecipient(user) - .withFrom(bot) - .withText("TEST Send to Conversation"); + Activity activity = new Activity(ActivityTypes.MESSAGE) {{ + setRecipient(user); + setFrom(bot); + setText("TEST Send to Conversation"); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.id(), activity); + ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); - Activity update = activity.withId(response.id()) - .withText("TEST Update Activity"); + activity.setId(response.getId()); + activity.setText("TEST Update Activity"); try { - ResourceResponse updateResponse = connector.conversations().updateActivity("B21S8SG7K:T03CWQ0QB", response.id(), update); + ResourceResponse updateResponse = connector.conversations().updateActivity("B21S8SG7K:T03CWQ0QB", response.getId(), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { - Assert.assertEquals("ServiceError", e.body().error().code().toString()); - Assert.assertTrue(e.body().error().message().contains("Invalid ConversationId")); + Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); + Assert.assertTrue(e.body().getError().getMessage().contains("Invalid ConversationId")); } } @Test public void UploadAttachment() { - AttachmentData attachment = new AttachmentData() - .withName("bot-framework.png") - .withType("image/png") - .withOriginalBase64(encodeToBase64(new File(getClass().getClassLoader().getResource("bot-framework.png").getFile()))); + AttachmentData attachment = new AttachmentData() {{ + setName("bot-framework.png"); + setType("image/png"); + setOriginalBase64(encodeToBase64(new File(getClass().getClassLoader().getResource("bot-framework.png").getFile()))); + }}; - ConversationParameters createMessage = new ConversationParameters() - .withMembers(Collections.singletonList(user)) - .withBot(bot); + ConversationParameters createMessage = new ConversationParameters() {{ + setMembers(Collections.singletonList(user)); + setBot(bot); + }}; ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().uploadAttachment(conversation.id(), attachment); + ResourceResponse response = connector.conversations().uploadAttachment(conversation.getId(), attachment); - Assert.assertNotNull(response.id()); + Assert.assertNotNull(response.getId()); } private byte[] encodeToBase64(File file) { try { FileInputStream fis = new FileInputStream(file); - byte[] result = new byte[(int)file.length()]; + byte[] result = new byte[(int) file.length()]; int size = fis.read(result); return result; } catch (Exception ex) { diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index 419e07301..c10ed1c2c 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -5,7 +5,7 @@ import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.bot.connector.authentication.*; -import com.microsoft.bot.schema.models.Activity; +import com.microsoft.bot.schema.Activity; import org.junit.Assert; import org.junit.Test; @@ -159,7 +159,9 @@ public void ChannelMsaHeaderValidServiceUrlShouldBeTrusted() throws IOException, String header = getHeaderToken(); CredentialProvider credentials = new SimpleCredentialProvider(APPID, ""); JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"), + new Activity() {{ + setServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"); + }}, header, credentials, new SimpleChannelProvider()).join(); @@ -177,7 +179,9 @@ public void ChannelMsaHeaderInvalidServiceUrlShouldNotBeTrusted() throws IOExcep try { JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://webchat.botframework.com/"), + new Activity() {{ + setServiceUrl("https://webchat.botframework.com/"); + }}, header, credentials, new SimpleChannelProvider()).join(); @@ -197,7 +201,9 @@ public void ChannelAuthenticationDisabledShouldBeAnonymous() throws ExecutionExc CredentialProvider credentials = new SimpleCredentialProvider("", ""); ClaimsIdentity identity = JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://webchat.botframework.com/"), + new Activity() {{ + setServiceUrl("https://webchat.botframework.com/"); + }}, header, credentials, new SimpleChannelProvider()).join(); @@ -210,7 +216,9 @@ public void ChannelNoHeaderAuthenticationEnabledShouldThrow() throws IOException String header = ""; CredentialProvider credentials = new SimpleCredentialProvider(APPID, APPPASSWORD); JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"), + new Activity() {{ + setServiceUrl("https://smba.trafficmanager.net/amer-client-ss.msg/"); + }}, header, credentials, new SimpleChannelProvider()).join(); @@ -231,7 +239,9 @@ public void ChannelAuthenticationDisabledServiceUrlShouldNotBeTrusted() throws E CredentialProvider credentials = new SimpleCredentialProvider("", ""); ClaimsIdentity identity = JwtTokenValidation.authenticateRequest( - new Activity().withServiceUrl("https://webchat.botframework.com/"), + new Activity() {{ + setServiceUrl("https://webchat.botframework.com/"); + }}, header, credentials, new SimpleChannelProvider()).join(); diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java index 615d3d2f8..6c2ab6064 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/OAuthTestBase.java @@ -6,7 +6,7 @@ import com.microsoft.bot.connector.authentication.OAuthClient; import com.microsoft.bot.connector.base.TestBase; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.ChannelAccount; +import com.microsoft.bot.schema.ChannelAccount; import com.microsoft.rest.RestClient; import java.io.IOException; @@ -17,10 +17,9 @@ import java.util.function.Function; -public class OAuthTestBase extends TestBase -{ +public class OAuthTestBase extends TestBase { protected String clientId; - protected String clientSecret ; + protected String clientSecret; protected final String userId = "U19KH8EHJ:T03CWQ0QB"; protected final String botId = "B21UTEF8S:T03CWQ0QB"; protected final static String hostUri = "https://slack.botframework.com"; @@ -30,17 +29,19 @@ public class OAuthTestBase extends TestBase protected RestConnectorClient connector; private ChannelAccount bot; + public ChannelAccount getBot() { return this.bot; } private ChannelAccount user; + public ChannelAccount getUser() { return this.user; } - public OAuthTestBase() { + public OAuthTestBase() { super(RunCondition.BOTH); } @@ -70,30 +71,27 @@ protected void initializeClients(RestClient restClient, String botId, String use MicrosoftAppCredentials credentials = new MicrosoftAppCredentials(this.clientId, this.clientSecret); this.token = credentials.getToken().get().getAccessToken(); - } - else { + } else { this.token = null; } - this.bot = new ChannelAccount() - .withId(botId); - this.user = new ChannelAccount() - .withId(userId); - - - + this.bot = new ChannelAccount(botId); + this.user = new ChannelAccount(userId); } @Override protected void cleanUpResources() { } + public void UseClientFor(Function> doTest) { this.UseClientFor(doTest, null, ""); } + public void UseClientFor(Function> doTest, String className) { this.UseClientFor(doTest, className, ""); } + public void UseClientFor(Function> doTest, String className, String methodName) { doTest.apply(this.connector).join(); } @@ -108,7 +106,7 @@ public CompletableFuture UseOAuthClientFor(Function UseOAuthClientFor(Function> doTest, String className, String methodName) throws MalformedURLException, URISyntaxException { - return CompletableFuture.runAsync(()->{ + return CompletableFuture.runAsync(() -> { OAuthClient oauthClient = null; try { oauthClient = new OAuthClient(this.connector, AuthenticationConstants.OAUTH_URL); diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActionTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActionTypes.java similarity index 59% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActionTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActionTypes.java index 4299a67e1..750a79e74 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActionTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActionTypes.java @@ -1,82 +1,107 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines action types for clickable buttons. - */ -public enum ActionTypes { - /** Enum value openUrl. */ - OPEN_URL("openUrl"), - - /** Enum value imBack. */ - IM_BACK("imBack"), - - /** Enum value postBack. */ - POST_BACK("postBack"), - - /** Enum value playAudio. */ - PLAY_AUDIO("playAudio"), - - /** Enum value playVideo. */ - PLAY_VIDEO("playVideo"), - - /** Enum value showImage. */ - SHOW_IMAGE("showImage"), - - /** Enum value downloadFile. */ - DOWNLOAD_FILE("downloadFile"), - - /** Enum value signin. */ - SIGNIN("signin"), - - /** Enum value call. */ - CALL("call"), - - /** Enum value payment. */ - PAYMENT("payment"), - - /** Enum value messageBack. */ - MESSAGE_BACK("messageBack"); - - /** The actual serialized value for a ActionTypes instance. */ - private String value; - - ActionTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ActionTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed ActionTypes object, or null if unable to parse. - */ - @JsonCreator - public static ActionTypes fromString(String value) { - ActionTypes[] items = ActionTypes.values(); - for (ActionTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines action types for clickable buttons. + */ +public enum ActionTypes { + /** + * Enum value openUrl. + */ + OPEN_URL("openUrl"), + + /** + * Enum value imBack. + */ + IM_BACK("imBack"), + + /** + * Enum value postBack. + */ + POST_BACK("postBack"), + + /** + * Enum value playAudio. + */ + PLAY_AUDIO("playAudio"), + + /** + * Enum value playVideo. + */ + PLAY_VIDEO("playVideo"), + + /** + * Enum value showImage. + */ + SHOW_IMAGE("showImage"), + + /** + * Enum value downloadFile. + */ + DOWNLOAD_FILE("downloadFile"), + + /** + * Enum value signin. + */ + SIGNIN("signin"), + + /** + * Enum value call. + */ + CALL("call"), + + /** + * Enum value payment. + */ + PAYMENT("payment"), + + /** + * Enum value messageBack. + */ + MESSAGE_BACK("messageBack"); + + /** + * The actual serialized value for a ActionTypes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + ActionTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ActionTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed ActionTypes object, or null if unable to parse. + */ + @JsonCreator + public static ActionTypes fromString(String value) { + ActionTypes[] items = ActionTypes.values(); + for (ActionTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java new file mode 100644 index 000000000..e6a039cd5 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java @@ -0,0 +1,1191 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * The Activity class contains all properties that individual, more specific activities + * could contain. It is a superset type. + */ +public class Activity { + /** + * Content-type for an Activity. + */ + private static final ObjectMapper MAPPER = new ObjectMapper(); + + /** + * The type of the activity. Possible values include: 'message', + * 'contactRelationUpdate', 'conversationUpdate', 'typing', 'ping', + * 'endOfConversation', 'event', 'invoke', 'deleteUserData', + * 'messageUpdate', 'messageDelete', 'installationUpdate', + * 'messageReaction', 'suggestion', 'trace'. + */ + @JsonProperty(value = "type") + private ActivityTypes type; + /** + * Contains an ID that uniquely identifies the activity on the channel. + */ + @JsonProperty(value = "id") + private String id; + /** + * Contains the date and time that the message was sent, in UTC, expressed in ISO-8601 format. + */ + @JsonProperty(value = "timestamp") + private DateTime timestamp; + /** + * Contains the local date and time of the message, expressed in ISO-8601 format. + * For example, 2016-09-23T13:07:49.4714686-07:00. + */ + @JsonProperty(value = "localTimestamp") + private DateTime localTimestamp; + /** + * Contains the name of the local timezone of the message, expressed in IANA Time Zone database format. + * For example, America/Los_Angeles. + */ + @JsonProperty(value = "localTimezone") + private String localTimezone; + /** + * A string containing an IRI identifying the caller of a bot. This field is not intended to be transmitted + * over the wire, but is instead populated by bots and clients based on cryptographically verifiable data + * that asserts the identity of the callers (e.g. tokens). + */ + @JsonProperty(value = "callerId") + private String callerId; + /** + * Contains the URL that specifies the channel's service endpoint. Set by the channel. + */ + @JsonProperty(value = "serviceUrl") + private String serviceUrl; + /** + * Contains an ID that uniquely identifies the channel. Set by the channel. + */ + @JsonProperty(value = "channelId") + private String channelId; + /** + * Identifies the sender of the message. + */ + @JsonProperty(value = "from") + private ChannelAccount from; + /** + * Identifies the conversation to which the activity belongs. + */ + @JsonProperty(value = "conversation") + private ConversationAccount conversation; + /** + * Identifies the recipient of the message. + */ + @JsonProperty(value = "recipient") + private ChannelAccount recipient; + /** + * Format of text fields Default:markdown. Possible values include: + * 'markdown', 'plain', 'xml'. + */ + @JsonProperty(value = "textFormat") + private TextFormatTypes textFormat; + /** + * The layout hint for multiple attachments. Default: list. + */ + @JsonProperty(value = "attachmentLayout") + private AttachmentLayoutTypes attachmentLayout; + /** + * The collection of members added to the conversation. + */ + @JsonProperty(value = "membersAdded") + private List membersAdded; + /** + * The collection of members removed from the conversation. + */ + @JsonProperty(value = "membersRemoved") + private List membersRemoved; + /** + * The collection of reactions added to the conversation. + */ + @JsonProperty(value = "reactionsAdded") + private List reactionsAdded; + /** + * The collection of reactions removed from the conversation. + */ + @JsonProperty(value = "reactionsRemoved") + private List reactionsRemoved; + /** + * The updated topic name of the conversation. + */ + @JsonProperty(value = "topicName") + private String topicName; + /** + * Indicates whether the prior history of the channel is disclosed. + */ + @JsonProperty(value = "historyDisclosed") + private boolean historyDisclosed; + /** + * A locale name for the contents of the text field. + * The locale name is a combination of an ISO 639 two- or three-letter culture code associated with a language + * and an ISO 3166 two-letter subculture code associated with a country or region. + *

+ * The locale name can also correspond to a valid BCP-47 language tag. + */ + @JsonProperty(value = "locale") + private String locale; + /** + * The text content of the message. + */ + @JsonProperty(value = "text") + private String text; + /** + * The text to speak. + */ + @JsonProperty(value = "speak") + private String speak; + /** + * Indicates whether your bot is accepting, expecting, or ignoring user input after the message + * is delivered to the client. + */ + @JsonProperty(value = "inputHint") + private InputHints inputHint; + /** + * The text to display if the channel cannot render cards. + */ + @JsonProperty(value = "summary") + private String summary; + /** + * The suggested actions for the activity. + */ + @JsonProperty(value = "suggestedActions") + private SuggestedActions suggestedActions; + /** + * Attachments. + */ + @JsonProperty(value = "attachments") + private List attachments; + /** + * Represents the entities that were mentioned in the message. + */ + @JsonProperty(value = "entities") + private List entities; + /** + * Contains channel-specific content. + */ + @JsonProperty(value = "channelData") + private Object channelData; + /** + * Indicates whether the recipient of a contactRelationUpdate was added or removed from the sender's contact list. + */ + @JsonProperty(value = "action") + private String action; + /** + * Contains the ID of the message to which this message is a reply. + */ + @JsonProperty(value = "replyToId") + private String replyToId; + /** + * A descriptive label for the activity. + */ + @JsonProperty(value = "label") + private String label; + /** + * The type of the activity's value object. + */ + @JsonProperty(value = "valueType") + private String valueType; + /** + * A value that is associated with the activity. + */ + @JsonProperty(value = "value") + private Object value; + /** + * The name of the operation associated with an invoke or event activity. + */ + @JsonProperty(value = "name") + private String name; + /** + * A reference to another conversation or activity. + */ + @JsonProperty(value = "relatesTo") + private ConversationReference relatesTo; + /** + * The a code for endOfConversation activities that indicates why the conversation ended. + */ + @JsonProperty(value = "code") + private EndOfConversationCodes code; + /** + * The time at which the activity should be considered to be expired and should not be presented to the recipient. + */ + @JsonProperty(value = "expiration") + private DateTime expiration; + /** + * The importance of the activity. + */ + @JsonProperty(value = "importance") + private String importance; + /** + * A delivery hint to signal to the recipient alternate delivery paths for the activity. + *

+ * The default delivery mode is \"default\". + */ + @JsonProperty(value = "deliveryMode") + private String deliveryMode; + /** + * List of phrases and references that speech and language priming systems should listen for. + */ + @JsonProperty(value = "listenFor") + private List listenFor; + /** + * The collection of text fragments to highlight when the activity contains a ReplyToId value. + */ + @JsonProperty(value = "textHighlights") + private List textHighlights; + /** + * Holds the overflow properties that aren't first class + * properties in the object. This allows extensibility + * while maintaining the object. + */ + private HashMap properties = new HashMap<>(); + + /** + * Default constructor. Normally this wouldn't be used as the ActivityType is normally required. + */ + protected Activity() { + setTimestamp(DateTime.now()); + } + + /** + * Construct an Activity of the specified type. + * @param withType The activity type. + */ + public Activity(ActivityTypes withType) { + this(); + setType(withType); + } + + /** + * Create a TRACE type Activity. + * + * @param withName Name of the operation + * @param withValueType valueType if helpful to identify the value schema (default is value.GetType().Name) + */ + public static Activity createTraceActivity(String withName, Object withValue, String withValueType, String withLabel) { + return new Activity(ActivityTypes.TRACE) {{ + setName(withName); + setLabel(withLabel); + setValueType((withValueType == null) ? withValue.getClass().getTypeName() : withValueType); + setValue(withValue); + }}; + } + + /** + * Create a MESSAGE type Activity. + * @return A message Activity type. + */ + public static Activity createMessageActivity() { + return new Activity(ActivityTypes.MESSAGE) {{ + setAttachments(new ArrayList<>()); + setEntities(new ArrayList<>()); + }}; + } + + /** + * Create a CONTACT_RELATION_UPDATE type Activity. + * @return A contact relation update type Activity. + */ + public static Activity createContactRelationUpdateActivity() { + return new Activity(ActivityTypes.CONTACT_RELATION_UPDATE); + } + + /** + * Create a CONVERSATION_UPDATE type Activity. + * @return A conversation update type Activity. + */ + public static Activity createConversationUpdateActivity() { + return new Activity(ActivityTypes.CONVERSATION_UPDATE) {{ + setMembersAdded(new ArrayList<>()); + setMembersRemoved(new ArrayList<>()); + }}; + } + + /** + * Creates a TYPING type Activity. + * @return The new typing activity. + */ + public static Activity createTypingActivity() { + return new Activity(ActivityTypes.TYPING); + } + + /** + * Creates a HANDOFF type Activity. + * @return The new handoff activity. + */ + public static Activity createHandoffActivity() { + return new Activity(ActivityTypes.HANDOFF); + } + + /** + * Creates a END_OF_CONVERSATION type of Activity. + * @return The new end of conversation activity. + */ + public static Activity createEndOfConversationActivity() { + return new Activity(ActivityTypes.END_OF_CONVERSATION); + } + + /** + * Creates a EVENT type of Activity. + * @return The new event activity. + */ + public static Activity createEventActivity() { + return new Activity(ActivityTypes.EVENT); + } + + /** + * Creates a INVOKE type of Activity. + * @return The new invoke activity. + */ + public static Activity createInvokeActivity() { + return new Activity(ActivityTypes.INVOKE); + } + + /** + * Clone a activity. + * + * @param activity The activity to clone. + * @return new cloned activity + */ + public static Activity cloneActivity(Activity activity) { + //TODO: This isn't a deep copy + Activity clone = new Activity(activity.getType()) {{ + setId(activity.getId()); + setTimestamp(activity.getTimestamp()); + setLocalTimestamp(activity.getLocalTimestamp()); + setChannelData(activity.getChannelData()); + setFrom(activity.getFrom()); + setRecipient(activity.getRecipient()); + setConversation(activity.getConversation()); + setChannelId(activity.getChannelId()); + setServiceUrl(activity.getServiceUrl()); + setChannelId(activity.getChannelId()); + setEntities(activity.getEntities()); + setReplyToId(activity.getReplyToId()); + setSpeak(activity.getSpeak()); + setText(activity.getText()); + setInputHint(activity.getInputHint()); + setSummary(activity.getSummary()); + setSuggestedActions(activity.getSuggestedActions()); + setAttachments(activity.getAttachments()); + setAction(activity.getAction()); + setLabel(activity.getLabel()); + setValueType(activity.getValueType()); + setValue(activity.getValue()); + setName(activity.getName()); + setRelatesTo(activity.getRelatesTo()); + setCode(activity.getCode()); + setExpiration(activity.getExpiration()); + setImportance(activity.getImportance()); + setDeliveryMode(activity.getDeliveryMode()); + setTextHighlights(activity.getTextHighlights()); + }}; + + for (Map.Entry entry : activity.getProperties().entrySet()) { + clone.setProperties(entry.getKey(), entry.getValue()); + } + + return clone; + } + + /** + * @see #type + */ + public ActivityTypes getType() { + return this.type; + } + + /** + * @see #type + */ + public void setType(ActivityTypes withType) { + this.type = withType; + } + + /** + * @see #id + */ + public String getId() { + return this.id; + } + + /** + * @see #id + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * @see #timestamp + */ + public DateTime getTimestamp() { + return this.timestamp; + } + + /** + * @see #timestamp + */ + public void setTimestamp(DateTime withTimestamp) { + this.timestamp = withTimestamp; + } + + /** + * @see #localTimestamp + */ + public DateTime getLocalTimestamp() { + return this.localTimestamp; + } + + /** + * @see #localTimestamp + */ + public void setLocalTimestamp(DateTime withLocalTimestamp) { + this.localTimestamp = withLocalTimestamp; + } + + /** + * @see #localTimezone + */ + public String getLocalTimezone() { + return this.localTimezone; + } + + /** + * @see #localTimezone + */ + public void setLocalTimeZone(String withLocalTimezone) { + this.localTimezone = withLocalTimezone; + } + + /** + * @see #callerId + */ + public String getCallerId() { + return this.callerId; + } + + /** + * @see #callerId + */ + public void setCallerId(String withCallerId) { + this.callerId = withCallerId; + } + + /** + * @see #serviceUrl + */ + public String getServiceUrl() { + return this.serviceUrl; + } + + /** + * @see #serviceUrl + */ + public void setServiceUrl(String withServiceUrl) { + this.serviceUrl = withServiceUrl; + } + + /** + * @see #channelId + */ + public String getChannelId() { + return this.channelId; + } + + /** + * @see #channelId + */ + public void setChannelId(String withChannelId) { + this.channelId = withChannelId; + } + + /** + * @see #from + */ + public ChannelAccount getFrom() { + return this.from; + } + + /** + * @see #from + */ + public void setFrom(ChannelAccount withFrom) { + this.from = withFrom; + } + + /** + * @see #conversation + */ + public ConversationAccount getConversation() { + return this.conversation; + } + + /** + * @see #conversation + */ + public void setConversation(ConversationAccount withConversation) { + this.conversation = withConversation; + } + + /** + * @see #recipient + */ + public ChannelAccount getRecipient() { + return this.recipient; + } + + /** + * @see #recipient + */ + public void setRecipient(ChannelAccount withRecipient) { + this.recipient = withRecipient; + } + + /** + * @see #textFormat + */ + public TextFormatTypes getTextFormat() { + return this.textFormat; + } + + /** + * @see #textFormat + */ + public void setTextFormat(TextFormatTypes withTextFormat) { + this.textFormat = withTextFormat; + } + + /** + * @see #attachmentLayout + */ + public AttachmentLayoutTypes getAttachmentLayout() { + return this.attachmentLayout; + } + + /** + * @see #attachmentLayout + */ + public void setAttachmentLayout(AttachmentLayoutTypes withAttachmentLayout) { + this.attachmentLayout = withAttachmentLayout; + } + + /** + * @see #reactionsAdded + */ + public List getReactionsAdded() { + return this.reactionsAdded; + } + + /** + * @see #reactionsAdded + */ + public void setReactionsAdded(List withReactionsAdded) { + this.reactionsAdded = withReactionsAdded; + } + + /** + * @see #reactionsRemoved + */ + public List getReactionsRemoved() { + return this.reactionsRemoved; + } + + /** + * @see #reactionsRemoved + */ + public void setReactionsRemoved(List withReactionsRemoved) { + this.reactionsRemoved = withReactionsRemoved; + } + + /** + * @see #locale + */ + public String getLocale() { + return this.locale; + } + + /** + * @see #locale + */ + public void setLocale(String withLocale) { + this.locale = withLocale; + } + + /** + * @see #text + */ + public String getText() { + return this.text; + } + + /** + * @see #text + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * @see #speak + */ + public String getSpeak() { + return this.speak; + } + + /** + * @see #speak + */ + public void setSpeak(String withSpeak) { + this.speak = withSpeak; + } + + /** + * @see #inputHint + */ + public InputHints getInputHint() { + return this.inputHint; + } + + /** + * @see #inputHint + */ + public void setInputHint(InputHints withInputHint) { + this.inputHint = withInputHint; + } + + /** + * @see #summary + */ + public String getSummary() { + return this.summary; + } + + /** + * @see #summary + */ + public void setSummary(String withSummary) { + this.summary = withSummary; + } + + /** + * @see #suggestedActions + */ + public SuggestedActions getSuggestedActions() { + return this.suggestedActions; + } + + /** + * @see #suggestedActions + */ + public void setSuggestedActions(SuggestedActions withSuggestedActions) { + this.suggestedActions = withSuggestedActions; + } + + /** + * @see #attachments + */ + public List getAttachments() { + return this.attachments; + } + + /** + * @see #attachments + */ + public void setAttachments(List withAttachments) { + this.attachments = withAttachments; + } + + /** + * @see #entities + */ + public List getEntities() { + return this.entities; + } + + /** + * @see #entities + */ + public void setEntities(List withEntities) { + this.entities = withEntities; + } + + /** + * @see #channelData + */ + public Object getChannelData() { + return this.channelData; + } + + /** + * @see #channelData + */ + public void setChannelData(Object withChannelData) { + this.channelData = withChannelData; + } + + /** + * @see #replyToId + */ + public String getReplyToId() { + return this.replyToId; + } + + /** + * @see #replyToId + */ + public void setReplyToId(String withReplyToId) { + this.replyToId = withReplyToId; + } + + /** + * @see #code + */ + public EndOfConversationCodes getCode() { + return this.code; + } + + /** + * @see #code + */ + public void setCode(EndOfConversationCodes withCode) { + this.code = withCode; + } + + /** + * @see #expiration + */ + public DateTime getExpiration() { + return this.expiration; + } + + /** + * @see #expiration + */ + public void setExpiration(DateTime withExpiration) { + this.expiration = withExpiration; + } + + /** + * @see #importance + */ + public String getImportance() { + return this.importance; + } + + /** + * @see #importance + */ + public void setImportance(String withImportance) { + this.importance = withImportance; + } + + /** + * @see #deliveryMode + */ + public String getDeliveryMode() { + return this.deliveryMode; + } + + /** + * @see #deliveryMode + */ + public void setDeliveryMode(String withDeliveryMode) { + this.deliveryMode = withDeliveryMode; + } + + /** + * @see #listenFor + */ + public List getListenFor() { + return this.listenFor; + } + + /** + * @see #listenFor + */ + public void setListenFor(List withListenFor) { + this.listenFor = withListenFor; + } + + /** + * @see #textHighlights + */ + public List getTextHighlights() { + return this.textHighlights; + } + + /** + * @see #textHighlights + */ + public void setTextHighlights(List withTextHighlights) { + this.textHighlights = withTextHighlights; + } + + /** + * @see #properties + */ + @JsonAnyGetter + public Map getProperties() { + return this.properties; + } + + /** + * @see #properties + */ + @JsonAnySetter + public void setProperties(String key, JsonNode value) { + this.properties.put(key, value); + } + + /** + * @see #topicName + */ + public String getTopicName() { + return this.topicName; + } + + /** + * @see #topicName + */ + public void setTopicName(String withTopicName) { + this.topicName = withTopicName; + } + + /** + * @see #historyDisclosed + */ + public boolean getHistoryDisclosed() { + return this.historyDisclosed; + } + + /** + * @see #historyDisclosed + */ + public void setHistoryDisclosed(boolean withHistoryDisclosed) { + this.historyDisclosed = withHistoryDisclosed; + } + + /** + * @see #membersAdded + */ + public List getMembersAdded() { + return this.membersAdded; + } + + /** + * @see #membersAdded + */ + public void setMembersAdded(List withMembersAdded) { + this.membersAdded = withMembersAdded; + } + + /** + * @see #membersRemoved + */ + public List getMembersRemoved() { + return this.membersRemoved; + } + + /** + * @see #membersRemoved + */ + public void setMembersRemoved(List withMembersRemoved) { + this.membersRemoved = withMembersRemoved; + } + + /** + * @see #label + */ + public String getLabel() { + return this.label; + } + + /** + * @see #label + */ + public void setLabel(String withLabel) { + this.label = withLabel; + } + + /** + * @see #valueType + */ + public String getValueType() { + return this.valueType; + } + + /** + * @see #valueType + */ + public void setValueType(String withValueType) { + this.valueType = withValueType; + } + + /** + * @see #value + */ + public Object getValue() { + return this.value; + } + + /** + * @see #value + */ + public void setValue(Object withValue) { + this.value = withValue; + } + + /** + * @see #name + */ + public String getName() { + return this.name; + } + + /** + * @see #name + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * @see #relatesTo + */ + public ConversationReference getRelatesTo() { + return this.relatesTo; + } + + /** + * @see #relatesTo + */ + public void setRelatesTo(ConversationReference withRelatesTo) { + this.relatesTo = withRelatesTo; + } + + /** + * @see #action + */ + public String getAction() { + return this.action; + } + + /** + * @see #action + */ + public void setAction(String withAction) { + this.action = withAction; + } + + public Activity createTrace(String withName, Object withValue, String withValueType, String withLabel) { + Activity reply = new Activity(ActivityTypes.TRACE); + + reply.setName(withName); + reply.setLabel(withLabel); + reply.setValueType((withValueType == null) ? withValue.getClass().getTypeName() : withValueType); + reply.setValue(withValue); + + reply.setFrom(new ChannelAccount(this.getRecipient().getId(), this.getRecipient().getName())); + reply.setRecipient(new ChannelAccount(this.getFrom().getId(), this.getFrom().getName())); + reply.setReplyToId(this.getId()); + reply.setServiceUrl(this.getServiceUrl()); + reply.setChannelId(this.getChannelId()); + reply.setConversation(new ConversationAccount( + this.getConversation().isGroup(), + this.getConversation().getId(), + this.getConversation().getName())); + + return reply; + } + + public Activity createReply(String withText) { + return createReply(withText, null); + } + + /** + * Creates a new message activity as a response to this activity. + * + * @param withText The text of the reply. + * @param withLocale The language code for the text. + * @return The new message activity. + */ + public Activity createReply(String withText, String withLocale) { + Activity result = new Activity(ActivityTypes.MESSAGE); + + result.setText((withText == null) ? "" : withText); + result.setLocale((withLocale == null) ? this.getLocale() : withLocale); + result.setFrom(new ChannelAccount( + this.getRecipient().getId(), + this.getRecipient().getName())); + result.setRecipient(new ChannelAccount( + this.getFrom().getId(), + this.getFrom().getName())); + result.setReplyToId(this.getId()); + result.setServiceUrl(this.getServiceUrl()); + result.setChannelId(this.getChannelId()); + result.setConversation(new ConversationAccount( + this.getConversation().isGroup(), + this.getConversation().getId(), + this.getConversation().getName())); + result.setAttachments(new ArrayList<>()); + result.setEntities(new ArrayList<>()); + + return result; + } + + /** + * Checks if this (message) activity has content. + * + * @return Returns true, if this message has any content to send. False otherwise. + */ + public boolean hasContent() { + if (!StringUtils.isBlank(this.getText())) + return true; + + if (!StringUtils.isBlank(this.getSummary())) + return true; + + if (this.getAttachments() != null && this.getAttachments().size() > 0) + return true; + + return this.getChannelData() != null; + } + + /** + * Resolves the mentions from the entities of this activity. + * + * This method is defined on the class, but is only intended for use with a + * message activity, where the activity {@link Activity#type} is set to {@link ActivityTypes#MESSAGE}. + * + * @return The array of mentions; or an empty array, if none are found. + */ + public List getMentions() { + return this.getEntities().stream() + .filter(entity -> entity.getType().equalsIgnoreCase("mention")) + .map(entity -> entity.getAs(Mention.class)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + /** + * Get channelData as typed structure + * + * @param classType type of TypeT to use + * @return typed Object or default(TypeT) + */ + public TypeT getChannelData(Class classType) throws JsonProcessingException { + if (this.getChannelData() == null) + return null; + + if (classType.isInstance(this.getChannelData())) { + return (TypeT) this.getChannelData(); + } + JsonNode node = MAPPER.valueToTree(this.getChannelData()); + return MAPPER.treeToValue(node, classType); + } + + /** + * Get channelData as typed structure + * + * @param clsType type of TypeT to use + * @return + */ + public ResultPair tryGetChannelData(Class clsType) { + TypeT instance = null; + if (this.getChannelData() == null) + return new ResultPair<>(false, instance); + + try { + instance = this.getChannelData(clsType); + } catch (JsonProcessingException e) { + return new ResultPair(false, instance); + } + return new ResultPair(true, instance); + } + + /** + * True if the Activity is of the specified activity type + */ + protected boolean isActivity(String activityType) { + /* + * NOTE: While it is possible to come up with a fancy looking "one-liner" to solve + * this problem, this code is purposefully more verbose due to optimizations. + * + * This main goal of the optimizations was to make zero allocations because it is called + * by all of the .AsXXXActivity methods which are used in a pattern heavily upstream to + * "pseudo-cast" the activity based on its type. + */ + + ActivityTypes type = this.getType(); + + // If there's no type set then we can't tell if it's the type they're looking for + if (type == null) { + return false; + } + + // Check if the full type value starts with the type they're looking for + + + boolean result = StringUtils.startsWith(type.toString().toLowerCase(), activityType.toLowerCase()); + + // If the full type value starts with the type they're looking for, then we need to check a little further to check if it's definitely the right type + if (result) { + // If the lengths are equal, then it's the exact type they're looking for + result = type.toString().length() == activityType.length(); + + if (!result) { + // Finally, if the type is longer than the type they're looking for then we need to check if there's a / separator right after the type they're looking for + result = type.toString().length() > activityType.length() + && + type.toString().indexOf(activityType.length()) == '/'; + } + } + + return result; + } + + public final Activity applyConversationReference(ConversationReference reference) { + return applyConversationReference(reference, false); + } + + public final Activity applyConversationReference(ConversationReference reference, boolean isIncoming) { + this.setChannelId(reference.getChannelId()); + this.setServiceUrl(reference.getServiceUrl()); + this.setConversation(reference.getConversation()); + + if (isIncoming) { + this.setFrom(reference.getUser()); + this.setRecipient(reference.getBot()); + if (reference.getActivityId() != null) { + this.setId(reference.getActivityId()); + } + } else // Outgoing + { + this.setFrom(reference.getBot()); + this.setRecipient(reference.getUser()); + if (reference.getActivityId() != null) { + this.setReplyToId(reference.getActivityId()); + } + } + return this; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImpl.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImpl.java deleted file mode 100644 index ef673d845..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImpl.java +++ /dev/null @@ -1,782 +0,0 @@ -package com.microsoft.bot.schema; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ActivityTypes; -import com.microsoft.bot.schema.models.Attachment; -import com.microsoft.bot.schema.models.ChannelAccount; -import com.microsoft.bot.schema.models.ConversationAccount; -import com.microsoft.bot.schema.models.ConversationReference; -import com.microsoft.bot.schema.models.ConversationUpdateActivity; -import com.microsoft.bot.schema.models.EndOfConversationCodes; -import com.microsoft.bot.schema.models.InputHints; -import com.microsoft.bot.schema.models.Mention; -import com.microsoft.bot.schema.models.MessageActivity; -import com.microsoft.bot.schema.models.SuggestedActions; -import com.microsoft.bot.schema.models.TextHighlight; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * An Activity is the basic communication type for the Bot Framework 3.0 protocol - * - * The Activity class contains all properties that individual, more specific activities - * could contain. It is a superset type. - * - */ -public class ActivityImpl extends Activity { - /** - * Content-type for an Activity - */ - public final String ContentType = "application/vnd.microsoft.activity"; - private static final ObjectMapper mapper = new ObjectMapper(); - - void CustomInit() { - } - - /** - * Take a message and create a reply message for it with the routing information - * set up to correctly route a reply to the source message - * @param text text you want to reply with - * @param locale language of your reply - * @return message set up to route back to the sender - */ - public ActivityImpl CreateReply() { - return CreateReply(null, null); - } - - public ActivityImpl CreateReply(String text) { - return CreateReply(text, null); - } - - public ActivityImpl CreateReply(String text, String locale) { - ActivityImpl reply = new ActivityImpl(); - reply.withType(ActivityTypes.MESSAGE); - reply.withTimestamp(DateTime.now()); - reply.withFrom(new ChannelAccount() - .withId(recipient().id()) - .withName(recipient().name())); - reply.withRecipient(new ChannelAccount() - .withId(from().id()) - .withName(from().name())); - reply.withReplyToId(this.id()); - reply.withServiceUrl(this.serviceUrl()); - reply.withChannelId(channelId()); - reply.withConversation(new ConversationAccount() - .withIsGroup(conversation().isGroup()) - .withId(conversation().id()) - .withName(conversation().name())); - reply.withText((text == null) ? "" : text); - reply.withLocale((locale == null) ? "" : locale); - reply.withAttachments(new ArrayList()); - reply.withEntities(new ArrayList()); - return reply; - } - - /** - * Create a trace activity based of this activity - * @param name Name of the operation - * @param value value of the operation - * @param valueType valueType if helpful to identify the value schema (default is value.GetType().Name) - * @param label descritive label of context. (Default is calling function name) - * @return - */ - public TraceActivity CreateTrace(String name) { - return CreateTrace(name, null, null, null); - } - - public TraceActivity CreateTrace(String name, Object value) { - return CreateTrace(name, value, null, null); - - } - - public TraceActivity CreateTrace(String name, Object value, String valueType) { - return CreateTrace(name, value, valueType, null); - } - - // public TraceActivity CreateTrace(String name, Object value, String valueType, [CallerMemberName] String label) - public TraceActivity CreateTrace(String name, Object value, String valueType, String label) { - TraceActivity reply = new TraceActivity(); - reply.withType(ActivityTypes.TRACE); - reply.withTimestamp(DateTime.now()); - reply.withFrom(new ChannelAccount() - .withId(recipient().id()) - .withName(recipient().name())); - reply.withRecipient(new ChannelAccount() - .withId(from().id()) - .withName(from().name())); - reply.withReplyToId(this.id()); - reply.withServiceUrl(this.serviceUrl()); - reply.withChannelId(channelId()); - reply.withConversation(new ConversationAccount() - .withIsGroup(conversation().isGroup()) - .withId(conversation().id()) - .withName(conversation().name())); - reply.withName(name); - reply.withLabel(label); - reply.withValueType((valueType == null) ? value.getClass().getTypeName() : valueType); - reply.withValue(value); - return reply; - } - - /** - * Create an instance of the TraceActivity - * @param name Name of the operation - * @param value value of the operation - * @param valueType valueType if helpful to identify the value schema (default is value.GetType().Name) - * @param label descritive label of context. (Default is calling function name) - */ - public static TraceActivity CreateTraceActivity(String name, String valueType) { - return CreateTraceActivity(name, valueType, null, null); - } - - public static TraceActivity CreateTraceActivity(String name, String valueType, Object value) { - return CreateTraceActivity(name, valueType, value, null); - } - - // public static TraceActivity CreateTraceActivity(String name, String valueType, Object value, [CallerMemberName] String label=null) - public static TraceActivity CreateTraceActivity(String name, String valueType, Object value, String label) { - TraceActivity reply = (TraceActivity) new TraceActivity(); - reply.withType(ActivityTypes.TRACE); - reply.withName(name); - reply.withLabel(label); - reply.withValueType((valueType == null) ? value.getClass().getTypeName() : valueType); - reply.withValue(value); - return reply; - - } - - /** - * Extension data for overflow of properties - */ - // [JsonExtensionData(ReadData = true, WriteData = true)] - //public JObject Properties { get; set; } = new JObject(); - - /** - * Create an instance of the Activity class with MessageActivity masking - */ - public static MessageActivity CreateMessageActivity() { - MessageActivity reply = new MessageActivity(); - reply.withType(ActivityTypes.TRACE); - reply.withTimestamp(DateTime.now()); - reply.withAttachments(new ArrayList()); - reply.withEntities(new ArrayList()); - return reply; - } - - /** - * Create an instance of the Activity class with IContactRelationUpdateActivity masking - */ - public static ContactRelationUpdateActivity CreateContactRelationUpdateActivity() { - ContactRelationUpdateActivity reply = new ContactRelationUpdateActivity(); - reply.withType(ActivityTypes.CONTACT_RELATION_UPDATE); - return reply; - } - - /** - * Create an instance of the Activity class with IConversationUpdateActivity masking - */ - public static ConversationUpdateActivity CreateConversationUpdateActivity() { - ConversationUpdateActivity reply = new ConversationUpdateActivity(); - reply.withType(ActivityTypes.CONVERSATION_UPDATE); - reply.withMembersAdded(new ArrayList()); - reply.withMembersRemoved(new ArrayList()); - return reply; - } - - /** - * Create an instance of the Activity class with ITypingActivity masking - */ - //public static TypingActivity CreateTypingActivity() { return new Activity(ActivityTypes.Typing); } - - /** - * Create an instance of the Activity class with IEndOfConversationActivity masking - */ - //public static IEndOfConversationActivity CreateEndOfConversationActivity() { return new Activity(ActivityTypes.EndOfConversation); } - - /** - * Create an instance of the Activity class with an IEventActivity masking - */ - //public static IEventActivity CreateEventActivity() { return new Activity(ActivityTypes.Event); } - - /** - * Create an instance of the Activity class with IInvokeActivity masking - */ - //public static IInvokeActivity CreateInvokeActivity() { return new Activity(ActivityTypes.Invoke); } - - - /** - * True if the Activity is of the specified activity type - */ - protected boolean IsActivity(String activityType) { - /* - * NOTE: While it is possible to come up with a fancy looking "one-liner" to solve - * this problem, this code is purposefully more verbose due to optimizations. - * - * This main goal of the optimizations was to make zero allocations because it is called - * by all of the .AsXXXActivity methods which are used in a pattern heavily upstream to - * "pseudo-cast" the activity based on its type. - */ - - ActivityTypes type = this.type(); - - // If there's no type set then we can't tell if it's the type they're looking for - if (type == null) { - return false; - } - - // Check if the full type value starts with the type they're looking for - - - boolean result = StringUtils.startsWith(type.toString().toLowerCase(), activityType.toLowerCase()); - - // If the full type value starts with the type they're looking for, then we need to check a little further to check if it's definitely the right type - if (result) { - // If the lengths are equal, then it's the exact type they're looking for - result = type.toString().length() == activityType.length(); - - if (!result) { - // Finally, if the type is longer than the type they're looking for then we need to check if there's a / separator right after the type they're looking for - result = type.toString().length() > activityType.length() - && - type.toString().indexOf(activityType.length()) == '/'; - } - } - - return result; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Activity object itself. - */ - public ActivityImpl withType(ActivityTypes type) { - super.withType(type); - return this; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the Activity object itself. - */ - public ActivityImpl withId(String id) { - super.withId(id); - return this; - } - - /** - * Set the timestamp value. - * - * @param timestamp the timestamp value to set - * @return the Activity object itself. - */ - public ActivityImpl withTimestamp(DateTime timestamp) { - super.withTimestamp(timestamp); - return this; - } - /** - * Set the localTimestamp value. - * - * @param localTimestamp the localTimestamp value to set - * @return the Activity object itself. - */ - public ActivityImpl withLocalTimestamp(DateTime localTimestamp) { - super.withLocalTimestamp(localTimestamp); - return this; - } - - /** - * Set the serviceUrl value. - * - * @param serviceUrl the serviceUrl value to set - * @return the Activity object itself. - */ - public ActivityImpl withServiceUrl(String serviceUrl) { - super.withServiceUrl(serviceUrl); - return this; - } - - /** - * Set the channelId value. - * - * @param channelId the channelId value to set - * @return the Activity object itself. - */ - public ActivityImpl withChannelId(String channelId) { - super.withChannelId(channelId); - return this; - } - /** - * Set the from value. - * - * @param from the from value to set - * @return the Activity object itself. - */ - public ActivityImpl withFrom(ChannelAccount from) { - super.withFrom(from); - return this; - } - /** - * Set the conversation value. - * - * @param conversation the conversation value to set - * @return the Activity object itself. - */ - public ActivityImpl withConversation(ConversationAccount conversation) { - super.withConversation(conversation); - return this; - } - /** - * Set the recipient value. - * - * @param recipient the recipient value to set - * @return the Activity object itself. - */ - public ActivityImpl withRecipient(ChannelAccount recipient) { - super.withRecipient(recipient); - return this; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the Activity object itself. - */ - public ActivityImpl withText(String text) { - super.withText(text); - return this; - } - - /** - * Set the speak value. - * - * @param speak the speak value to set - * @return the Activity object itself. - */ - public ActivityImpl withSpeak(String speak) { - super.withSpeak(speak); - return this; - } - - - /** - * Set the inputHint value. - * - * @param inputHint the inputHint value to set - * @return the Activity object itself. - */ - public ActivityImpl withInputHint(InputHints inputHint) { - super.withInputHint(inputHint); - return this; - } - - /** - * Set the summary value. - * - * @param summary the summary value to set - * @return the Activity object itself. - */ - public ActivityImpl withSummary(String summary) { - super.withSummary(summary); - return this; - } - - - /** - * Set the suggestedActions value. - * - * @param suggestedActions the suggestedActions value to set - * @return the Activity object itself. - */ - public ActivityImpl withSuggestedActions(SuggestedActions suggestedActions) { - super.withSuggestedActions(suggestedActions); - return this; - } - - - /** - * Set the attachments value. - * - * @param attachments the attachments value to set - * @return the Activity object itself. - */ - public ActivityImpl withAttachments(List attachments) { - super.withAttachments(attachments); - return this; - } - - - /** - * Set the entities value. - * - * @param entities the entities value to set - * @return the Activity object itself. - */ - public ActivityImpl withEntities(List entities) { - super.withEntities(entities); - return this; - } - - - /** - * Set the channelData value. - * - * @param channelData the channelData value to set - * @return the Activity object itself. - */ - public ActivityImpl withChannelData(Object channelData) { - super.withChannelData(channelData); - return this; - } - - - /** - * Set the action value. - * - * @param action the action value to set - * @return the Activity object itself. - */ - public ActivityImpl withAction(String action) { - super.withAction(action); - return this; - } - - /** - * Set the replyToId value. - * - * @param replyToId the replyToId value to set - * @return the Activity object itself. - */ - public ActivityImpl withReplyToId(String replyToId) { - super.withReplyToId(replyToId); - return this; - } - - /** - * Set the label value. - * - * @param label the label value to set - * @return the Activity object itself. - */ - public ActivityImpl withLabel(String label) { - super.withLabel(label); - return this; - } - - /** - * Set the valueType value. - * - * @param valueType the valueType value to set - * @return the Activity object itself. - */ - public ActivityImpl withValueType(String valueType) { - super.withValueType(valueType); - return this; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the Activity object itself. - */ - public ActivityImpl withValue(Object value) { - super.withValue(value); - return this; - } - - - /** - * Set the name value. - * - * @param name the name value to set - * @return the Activity object itself. - */ - public ActivityImpl withName(String name) { - super.withName(name); - return this; - } - - - /** - * Set the relatesTo value. - * - * @param relatesTo the relatesTo value to set - * @return the Activity object itself. - */ - public ActivityImpl withRelatesTo(ConversationReference relatesTo) { - super.withRelatesTo(relatesTo); - return this; - } - - /** - * Set the code value. - * - * @param code the code value to set - * @return the Activity object itself. - */ - public ActivityImpl withCode(EndOfConversationCodes code) { - super.withCode(code); - return this; - } - - /** - * Set the expiration value. - * - * @param expiration the expiration value to set - * @return the Activity object itself. - */ - public ActivityImpl withExpiration(DateTime expiration) { - super.withExpiration(expiration); - return this; - } - - /** - * Set the importance value. - * - * @param importance the importance value to set - * @return the Activity object itself. - */ - public ActivityImpl withImportance(String importance) { - super.withImportance(importance); - return this; - } - - /** - * Set the deliveryMode value. - * - * @param deliveryMode the deliveryMode value to set - * @return the Activity object itself. - */ - public ActivityImpl withDeliveryMode(String deliveryMode) { - super.withDeliveryMode(deliveryMode); - return this; - } - - /** - * Set the textHighlights value. - * - * @param textHighlights the textHighlights value to set - * @return the Activity object itself. - */ - public ActivityImpl withTextHighlights(List textHighlights) { - super.withTextHighlights(textHighlights); - return this; - } - - /** - * Return an MessageActivity mask if this is a message activity - */ - public MessageActivity AsMessageActivity() { - return IsActivity(ActivityTypes.MESSAGE.toString()) ? (MessageActivity) (Activity) this : null; - } - - /** - * Return an ContactRelationUpdateActivity mask if this is a contact relation update activity - */ - public ContactRelationUpdateActivity AsContactRelationUpdateActivity() { - return IsActivity(ActivityTypes.CONTACT_RELATION_UPDATE.toString()) ? (ContactRelationUpdateActivity) (Activity) this : null; - } - - - - /** - * Return an InstallationUpdateActivity mask if this is a installation update activity - */ - //public InstallationUpdateActivity AsInstallationUpdateActivity() { return IsActivity(ActivityTypes.INSTALLATION_UPDATE.toString()) ? this : null; } - - /** - * Return an ConversationUpdateActivity mask if this is a conversation update activity - */ - //public ConversationUpdateActivity AsConversationUpdateActivity() { return IsActivity(ActivityTypes.ConversationUpdate) ? this : null; } - - /** - * Return an TypingActivity mask if this is a typing activity - */ - // public TypingActivity AsTypingActivity() { return IsActivity(ActivityTypes.TYPING.toString()) ? (TypingActivity)(Activity)this : null; } - - /** - * Return an IEndOfConversationActivity mask if this is an end of conversation activity - */ - //public IEndOfConversationActivity AsEndOfConversationActivity() { return IsActivity(ActivityTypes.EndOfConversation) ? this : null; } - - /** - * Return an IEventActivity mask if this is an event activity - */ - //public IEventActivity AsEventActivity() { return IsActivity(ActivityTypes.Event) ? this : null; } - - /** - * Return an IInvokeActivity mask if this is an invoke activity - */ - //public IInvokeActivity AsInvokeActivity() { return IsActivity(ActivityTypes.Invoke) ? this : null; } - - /** - * Return an IMessageUpdateAcitvity if this is a MessageUpdate activity - * @return - */ - //public IMessageUpdateActivity AsMessageUpdateActivity() { return IsActivity(ActivityTypes.MessageUpdate) ? this : null; } - - /** - * Return an IMessageDeleteActivity if this is a MessageDelete activity - * @return - */ - //public IMessageDeleteActivity AsMessageDeleteActivity() { return IsActivity(ActivityTypes.MessageDelete) ? this : null; } - - /** - * Return an IMessageReactionActivity if this is a MessageReaction activity - * @return - */ - //public IMessageReactionActivity AsMessageReactionActivity() { return IsActivity(ActivityTypes.MessageReaction) ? this : null; } - - /** - * Return an ISuggestionActivity if this is a Suggestion activity - * @return - */ - //public ISuggestionActivity AsSuggestionActivity() { return IsActivity(ActivityTypes.Suggestion) ? this : null; } - - /** - * Return an ITraceActivity if this is a Trace activity - * @return - */ - //public ITraceActivity AsTraceActivity() { return IsActivity(ActivityTypes.Trace) ? this : null; } - - /** - * Checks if this (message) activity has content. - * @return Returns true, if this message has any content to send. False otherwise. - */ - public boolean HasContent() { - if (!StringUtils.isBlank(this.text())) - return true; - - if (!StringUtils.isBlank(this.summary())) - return true; - - if (this.attachments() != null && this.attachments().size() > 0) - return true; - - if (this.channelData() != null) - return true; - - return false; - } - - public Mention convertToMention(JsonNode node) { - try { - return ActivityImpl.mapper.treeToValue(node, Mention.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return null; - - } - /** - * Resolves the mentions from the entities of this (message) activity. - * @return The array of mentions or an empty array, if none found. - * TODO: Need to see how mentions are formated in the message - */ - public ArrayList GetMentions() { - ArrayList list = null; -// (ArrayList) this.entities().stream() -// .filter(entity -> entity.type().equalsIgnoreCase("mention")) -// .map(entity -> convertToMention(entity.getProperties())) -// .collect(Collectors.toCollection(ArrayList::new)); // create mutable list - return list; - } - - /** - * Get channeldata as typed structure - * @param activity - * @param TypeT type to use - * @return typed Object or default(TypeT) - */ - public TypeT GetChannelData(Class classType) throws JsonProcessingException { - if (this.channelData() == null) - return null; - - if (classType.isInstance(this.channelData())) { - return (TypeT) this.channelData(); - } - JsonNode node = mapper.valueToTree(this.channelData()); - return mapper.treeToValue((TreeNode) node, classType); - } - - /** - * Get channeldata as typed structure - * @param activity - * @param TypeT type to use - * @param instance The resulting instance, if possible - * @return - * {@code true} if value of {@linkalso Activity.ChannelData} was coerceable to {@code TypeT}, {@code false} otherwise. - */ - - public ResultPair TryGetChannelData(Class clsType) { - TypeT instance = null; - if (this.channelData() == null) - return new ResultPair<>(false, instance); - - try { - instance = this.GetChannelData(clsType); - } catch (JsonProcessingException e) { - return new ResultPair(false, instance); - } - return new ResultPair(true, instance); - } - /** - * Clone a activity - * @param activity - * @return new cloned activity - */ - public static Activity CloneActity(Activity activity) { - Activity clone = new Activity() - .withType(activity.type()) - .withId(activity.id()) - .withTimestamp(activity.timestamp()) - .withLocalTimestamp(activity.localTimestamp()) - .withText(activity.text()) - .withFrom(activity.from()) - .withRecipient(activity.recipient()) - .withConversation(activity.conversation()) - .withChannelId(activity.channelId()) - .withServiceUrl(activity.serviceUrl()) - .withChannelId(activity.channelId()) - .withText(activity.text()) - .withSpeak(activity.speak()) - .withInputHint(activity.inputHint()) - .withSummary(activity.summary()) - .withSuggestedActions(activity.suggestedActions()) - .withAttachments(activity.attachments()) - .withEntities(activity.entities()) - .withChannelData(activity.channelData()) - .withAction(activity.action()) - .withReplyToId(activity.replyToId()) - .withLabel(activity.label()) - .withValueType(activity.valueType()) - .withValue(activity.value()) - .withName(activity.name()) - .withRelatesTo(activity.relatesTo()) - .withCode(activity.code()) - .withExpiration(activity.expiration()) - .withImportance(activity.importance()) - .withDeliveryMode(activity.deliveryMode()) - .withTextHighlights(activity.textHighlights()); - for (Map.Entry entry : activity.properties().entrySet()) { - clone.setProperties(entry.getKey(), entry.getValue()); - } - return clone; - - } - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityImportance.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImportance.java similarity index 67% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityImportance.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImportance.java index 0ba0dc51c..e1a8b6458 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityImportance.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityImportance.java @@ -1,58 +1,67 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for ActivityImportance. - */ -public enum ActivityImportance { - /** Enum value low. */ - LOW("low"), - - /** Enum value normal. */ - NORMAL("normal"), - - /** Enum value high. */ - HIGH("high"); - - /** The actual serialized value for a ActivityImportance instance. */ - private String value; - - ActivityImportance(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ActivityImportance instance. - * - * @param value the serialized value to parse. - * @return the parsed ActivityImportance object, or null if unable to parse. - */ - @JsonCreator - public static ActivityImportance fromString(String value) { - ActivityImportance[] items = ActivityImportance.values(); - for (ActivityImportance item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for ActivityImportance. + */ +public enum ActivityImportance { + /** + * Enum value low. + */ + LOW("low"), + + /** + * Enum value normal. + */ + NORMAL("normal"), + + /** + * Enum value high. + */ + HIGH("high"); + + /** + * The actual serialized value for a ActivityImportance instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + ActivityImportance(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ActivityImportance instance. + * + * @param value the serialized value to parse. + * @return the parsed ActivityImportance object, or null if unable to parse. + */ + @JsonCreator + public static ActivityImportance fromString(String value) { + ActivityImportance[] items = ActivityImportance.values(); + for (ActivityImportance item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityTypes.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityTypes.java index d593a3106..3b9fe75f7 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ActivityTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ActivityTypes.java @@ -1,94 +1,127 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for ActivityTypes. - */ -public enum ActivityTypes { - /** Enum value message. */ - MESSAGE("message"), - - /** Enum value contactRelationUpdate. */ - CONTACT_RELATION_UPDATE("contactRelationUpdate"), - - /** Enum value conversationUpdate. */ - CONVERSATION_UPDATE("conversationUpdate"), - - /** Enum value typing. */ - TYPING("typing"), - - /** Enum value endOfConversation. */ - END_OF_CONVERSATION("endOfConversation"), - - /** Enum value event. */ - EVENT("event"), - - /** Enum value invoke. */ - INVOKE("invoke"), - - /** Enum value deleteUserData. */ - DELETE_USER_DATA("deleteUserData"), - - /** Enum value messageUpdate. */ - MESSAGE_UPDATE("messageUpdate"), - - /** Enum value messageDelete. */ - MESSAGE_DELETE("messageDelete"), - - /** Enum value installationUpdate. */ - INSTALLATION_UPDATE("installationUpdate"), - - /** Enum value messageReaction. */ - MESSAGE_REACTION("messageReaction"), - - /** Enum value suggestion. */ - SUGGESTION("suggestion"), - - /** Enum value trace. */ - TRACE("trace"), - - /** Enum value handoff. */ - HANDOFF("handoff"); - - /** The actual serialized value for a ActivityTypes instance. */ - private String value; - - ActivityTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ActivityTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed ActivityTypes object, or null if unable to parse. - */ - @JsonCreator - public static ActivityTypes fromString(String value) { - ActivityTypes[] items = ActivityTypes.values(); - for (ActivityTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for ActivityTypes. + */ +public enum ActivityTypes { + /** + * Enum value message. + */ + MESSAGE("message"), + + /** + * Enum value contactRelationUpdate. + */ + CONTACT_RELATION_UPDATE("contactRelationUpdate"), + + /** + * Enum value conversationUpdate. + */ + CONVERSATION_UPDATE("conversationUpdate"), + + /** + * Enum value typing. + */ + TYPING("typing"), + + /** + * Enum value endOfConversation. + */ + END_OF_CONVERSATION("endOfConversation"), + + /** + * Enum value event. + */ + EVENT("event"), + + /** + * Enum value invoke. + */ + INVOKE("invoke"), + + /** + * Enum value deleteUserData. + */ + DELETE_USER_DATA("deleteUserData"), + + /** + * Enum value messageUpdate. + */ + MESSAGE_UPDATE("messageUpdate"), + + /** + * Enum value messageDelete. + */ + MESSAGE_DELETE("messageDelete"), + + /** + * Enum value installationUpdate. + */ + INSTALLATION_UPDATE("installationUpdate"), + + /** + * Enum value messageReaction. + */ + MESSAGE_REACTION("messageReaction"), + + /** + * Enum value suggestion. + */ + SUGGESTION("suggestion"), + + /** + * Enum value trace. + */ + TRACE("trace"), + + /** + * Enum value handoff. + */ + HANDOFF("handoff"); + + /** + * The actual serialized value for a ActivityTypes instance. + */ + private String value; + + /** + * Creates a ActivityTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + ActivityTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ActivityTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed ActivityTypes object, or null if unable to parse. + */ + @JsonCreator + public static ActivityTypes fromString(String value) { + ActivityTypes[] items = ActivityTypes.values(); + for (ActivityTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AnimationCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java similarity index 54% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AnimationCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java index ce00f77bd..ab61d4cf1 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AnimationCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java @@ -1,332 +1,304 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An animation card (Ex: gif or short video clip). - */ -public class AnimationCard { - /** - * Title of this card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of this card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text of this card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Thumbnail placeholder. - */ - @JsonProperty(value = "image") - private ThumbnailUrl image; - - /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. - */ - @JsonProperty(value = "media") - private List media; - - /** - * Actions on this card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This content may be shared with others (default:true). - */ - @JsonProperty(value = "shareable") - private Boolean shareable; - - /** - * Should the client loop playback at end of content (default:true). - */ - @JsonProperty(value = "autoloop") - private Boolean autoloop; - - /** - * Should the client automatically start playback of media in this card - * (default:true). - */ - @JsonProperty(value = "autostart") - private Boolean autostart; - - /** - * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" - * and "4:3". - */ - @JsonProperty(value = "aspect") - private String aspect; - - /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. - */ - @JsonProperty(value = "duration") - private String duration; - - /** - * Supplementary parameter for this card. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public ThumbnailUrl image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withImage(ThumbnailUrl image) { - this.image = image; - return this; - } - - /** - * Get the media value. - * - * @return the media value - */ - public List media() { - return this.media; - } - - /** - * Set the media value. - * - * @param media the media value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withMedia(List media) { - this.media = media; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the shareable value. - * - * @return the shareable value - */ - public Boolean shareable() { - return this.shareable; - } - - /** - * Set the shareable value. - * - * @param shareable the shareable value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withShareable(Boolean shareable) { - this.shareable = shareable; - return this; - } - - /** - * Get the autoloop value. - * - * @return the autoloop value - */ - public Boolean autoloop() { - return this.autoloop; - } - - /** - * Set the autoloop value. - * - * @param autoloop the autoloop value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withAutoloop(Boolean autoloop) { - this.autoloop = autoloop; - return this; - } - - /** - * Get the autostart value. - * - * @return the autostart value - */ - public Boolean autostart() { - return this.autostart; - } - - /** - * Set the autostart value. - * - * @param autostart the autostart value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withAutostart(Boolean autostart) { - this.autostart = autostart; - return this; - } - - /** - * Get the aspect value. - * - * @return the aspect value - */ - public String aspect() { - return this.aspect; - } - - /** - * Set the aspect value. - * - * @param aspect the aspect value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withAspect(String aspect) { - this.aspect = aspect; - return this; - } - - /** - * Gets the duration value. - */ - public String duration(){ - return this.duration; - } - - /** - * Sets the duration value. - * - * @param duration the duration value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withDuration(String duration){ - this.duration = duration; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the AnimationCard object itself. - */ - public AnimationCard withValue(Object value) { - this.value = value; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * An animation card (Ex: gif or short video clip). + */ +public class AnimationCard { + /** + * Title of this card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of this card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text of this card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Thumbnail placeholder. + */ + @JsonProperty(value = "image") + private ThumbnailUrl image; + + /** + * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + */ + @JsonProperty(value = "media") + private List media; + + /** + * Actions on this card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This content may be shared with others (default:true). + */ + @JsonProperty(value = "shareable") + private boolean shareable; + + /** + * Should the client loop playback at end of content (default:true). + */ + @JsonProperty(value = "autoloop") + private boolean autoloop; + + /** + * Should the client automatically start playback of media in this card + * (default:true). + */ + @JsonProperty(value = "autostart") + private boolean autostart; + + /** + * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" + * and "4:3". + */ + @JsonProperty(value = "aspect") + private String aspect; + + /** + * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + */ + @JsonProperty(value = "duration") + private String duration; + + /** + * Supplementary parameter for this card. + */ + @JsonProperty(value = "value") + private Object value; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the image value. + * + * @return the image value + */ + public ThumbnailUrl getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(ThumbnailUrl withImage) { + this.image = withImage; + } + + /** + * Get the media value. + * + * @return the media value + */ + public List getMedia() { + return this.media; + } + + /** + * Set the media value. + * + * @param withMedia the media value to set + */ + public void setMedia(List withMedia) { + this.media = withMedia; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the shareable value. + * + * @return the shareable value + */ + public boolean getShareable() { + return this.shareable; + } + + /** + * Set the shareable value. + * + * @param withShareable the shareable value to set + */ + public void setShareable(boolean withShareable) { + this.shareable = withShareable; + } + + /** + * Get the autoloop value. + * + * @return the autoloop value + */ + public boolean getAutoloop() { + return this.autoloop; + } + + /** + * Set the autoloop value. + * + * @param withAutoloop the autoloop value to set + */ + public void setAutoloop(boolean withAutoloop) { + this.autoloop = withAutoloop; + } + + /** + * Get the autostart value. + * + * @return the autostart value + */ + public boolean getAutostart() { + return this.autostart; + } + + /** + * Set the autostart value. + * + * @param withAutostart the autostart value to set + */ + public void setAutostart(boolean withAutostart) { + this.autostart = withAutostart; + } + + /** + * Get the aspect value. + * + * @return the aspect value + */ + public String getAspect() { + return this.aspect; + } + + /** + * Set the aspect value. + * + * @param withAspect the aspect value to set + */ + public void setAspect(String withAspect) { + this.aspect = withAspect; + } + + /** + * Gets the duration value. + */ + public String getDuration() { + return this.duration; + } + + /** + * Sets the duration value. + * + * @param withDuration the duration value to set + */ + public void setDuration(String withDuration) { + this.duration = withDuration; + } + + /** + * Get the value value. + * + * @return the value value + */ + public Object getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(Object withValue) { + this.value = withValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Attachment.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java similarity index 65% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Attachment.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java index a0e4c51cd..4f255f321 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Attachment.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java @@ -1,185 +1,169 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; - -import java.util.HashMap; -import java.util.Map; - -/** - * An attachment within an activity. - */ -public class Attachment { - /** - * mimetype/Contenttype for the file. - */ - @JsonProperty(value = "contentType") - private String contentType; - - /** - * Content Url. - */ - @JsonProperty(value = "contentUrl") - private String contentUrl; - - /** - * Embedded content. - */ - @JsonProperty(value = "content") - private Object content; - - /** - * (OPTIONAL) The name of the attachment. - */ - @JsonProperty(value = "name") - private String name; - - /** - * (OPTIONAL) Thumbnail associated with attachment. - */ - @JsonProperty(value = "thumbnailUrl") - private String thumbnailUrl; - - /** - * Get the contentType value. - * - * @return the contentType value - */ - public String contentType() { - return this.contentType; - } - - /** - * Set the contentType value. - * - * @param contentType the contentType value to set - * @return the Attachment object itself. - */ - public Attachment withContentType(String contentType) { - this.contentType = contentType; - return this; - } - - /** - * Get the contentUrl value. - * - * @return the contentUrl value - */ - public String contentUrl() { - return this.contentUrl; - } - - /** - * Set the contentUrl value. - * - * @param contentUrl the contentUrl value to set - * @return the Attachment object itself. - */ - public Attachment withContentUrl(String contentUrl) { - this.contentUrl = contentUrl; - return this; - } - - /** - * Get the content value. - * - * @return the content value - */ - public Object content() { - return this.content; - } - - /** - * Set the content value. - * - * @param content the content value to set - * @return the Attachment object itself. - */ - public Attachment withContent(Object content) { - this.content = content; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the Attachment object itself. - */ - public Attachment withName(String name) { - this.name = name; - return this; - } - - /** - * Get the thumbnailUrl value. - * - * @return the thumbnailUrl value - */ - public String thumbnailUrl() { - return this.thumbnailUrl; - } - - /** - * Set the thumbnailUrl value. - * - * @param thumbnailUrl the thumbnailUrl value to set - * @return the Attachment object itself. - */ - public Attachment withThumbnailUrl(String thumbnailUrl) { - this.thumbnailUrl = thumbnailUrl; - return this; - } - /** - * Holds the overflow properties that aren't first class - * properties in the object. This allows extensibility - * while maintaining the object. - * - */ - private HashMap properties = new HashMap(); - - /** - * Overflow properties. - * Properties that are not modelled as first class properties in the object are accessible here. - * Note: A property value can be be nested. - * - * @return A Key-Value map of the properties - */ - @JsonAnyGetter - public Map properties() { - return this.properties; - } - - /** - * Set overflow properties. - * - * @param key Key for the property - * @param value JsonNode of value (can be nested) - * - */ - - @JsonAnySetter - public void setProperties(String key, JsonNode value) { - this.properties.put(key, value); - } - - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.HashMap; +import java.util.Map; + +/** + * An attachment within an activity. + */ +public class Attachment { + /** + * mimetype/Contenttype for the file. + */ + @JsonProperty(value = "contentType") + private String contentType; + + /** + * Content Url. + */ + @JsonProperty(value = "contentUrl") + private String contentUrl; + + /** + * Embedded content. + */ + @JsonProperty(value = "content") + private Object content; + + /** + * (OPTIONAL) The name of the attachment. + */ + @JsonProperty(value = "name") + private String name; + + /** + * (OPTIONAL) Thumbnail associated with attachment. + */ + @JsonProperty(value = "thumbnailUrl") + private String thumbnailUrl; + /** + * Holds the overflow properties that aren't first class + * properties in the object. This allows extensibility + * while maintaining the object. + */ + private HashMap properties = new HashMap(); + + /** + * Get the contentType value. + * + * @return the contentType value + */ + public String getContentType() { + return this.contentType; + } + + /** + * Set the contentType value. + * + * @param withContentType the contentType value to set + */ + public void setContentType(String withContentType) { + this.contentType = withContentType; + } + + /** + * Get the contentUrl value. + * + * @return the contentUrl value + */ + public String getContentUrl() { + return this.contentUrl; + } + + /** + * Set the contentUrl value. + * + * @param withContentUrl the contentUrl value to set + */ + public void setContentUrl(String withContentUrl) { + this.contentUrl = withContentUrl; + } + + /** + * Get the content value. + * + * @return the content value + */ + public Object getContent() { + return this.content; + } + + /** + * Set the content value. + * + * @param withContent the content value to set + */ + public void setContent(Object withContent) { + this.content = withContent; + } + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * Get the thumbnailUrl value. + * + * @return the thumbnailUrl value + */ + public String getThumbnailUrl() { + return this.thumbnailUrl; + } + + /** + * Set the thumbnailUrl value. + * + * @param withThumbnailUrl the thumbnailUrl value to set + */ + public void setThumbnailUrl(String withThumbnailUrl) { + this.thumbnailUrl = withThumbnailUrl; + } + + /** + * Overflow properties. + * Properties that are not modelled as first class properties in the object are accessible here. + * Note: A property value can be be nested. + * + * @return A Key-Value map of the properties + */ + @JsonAnyGetter + public Map getProperties() { + return this.properties; + } + + /** + * Set overflow properties. + * + * @param key Key for the property + * @param value JsonNode of value (can be nested) + */ + @JsonAnySetter + public void setProperties(String key, JsonNode value) { + this.properties.put(key, value); + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentData.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentData.java similarity index 53% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentData.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentData.java index e58585d9d..a0950bce7 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentData.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentData.java @@ -1,123 +1,111 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Attachment data. - */ -public class AttachmentData { - /** - * Content-Type of the attachment. - */ - @JsonProperty(value = "type") - private String type; - - /** - * Name of the attachment. - */ - @JsonProperty(value = "name") - private String name; - - /** - * Attachment content. - */ - @JsonProperty(value = "originalBase64") - private byte[] originalBase64; - - /** - * Attachment thumbnail. - */ - @JsonProperty(value = "thumbnailBase64") - private byte[] thumbnailBase64; - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the AttachmentData object itself. - */ - public AttachmentData withType(String type) { - this.type = type; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the AttachmentData object itself. - */ - public AttachmentData withName(String name) { - this.name = name; - return this; - } - - /** - * Get the originalBase64 value. - * - * @return the originalBase64 value - */ - public byte[] originalBase64() { - return this.originalBase64; - } - - /** - * Set the originalBase64 value. - * - * @param originalBase64 the originalBase64 value to set - * @return the AttachmentData object itself. - */ - public AttachmentData withOriginalBase64(byte[] originalBase64) { - this.originalBase64 = originalBase64; - return this; - } - - /** - * Get the thumbnailBase64 value. - * - * @return the thumbnailBase64 value - */ - public byte[] thumbnailBase64() { - return this.thumbnailBase64; - } - - /** - * Set the thumbnailBase64 value. - * - * @param thumbnailBase64 the thumbnailBase64 value to set - * @return the AttachmentData object itself. - */ - public AttachmentData withThumbnailBase64(byte[] thumbnailBase64) { - this.thumbnailBase64 = thumbnailBase64; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Attachment data. + */ +public class AttachmentData { + /** + * Content-Type of the attachment. + */ + @JsonProperty(value = "type") + private String type; + + /** + * Name of the attachment. + */ + @JsonProperty(value = "name") + private String name; + + /** + * Attachment content. + */ + @JsonProperty(value = "originalBase64") + private byte[] originalBase64; + + /** + * Attachment thumbnail. + */ + @JsonProperty(value = "thumbnailBase64") + private byte[] thumbnailBase64; + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Set the type value. + * + * @param withType the type value to set + */ + public void setType(String withType) { + this.type = withType; + } + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * Get the originalBase64 value. + * + * @return the originalBase64 value + */ + public byte[] getOriginalBase64() { + return this.originalBase64; + } + + /** + * Set the originalBase64 value. + * + * @param withOriginalBase64 the originalBase64 value to set + */ + public void setOriginalBase64(byte[] withOriginalBase64) { + this.originalBase64 = withOriginalBase64; + } + + /** + * Get the thumbnailBase64 value. + * + * @return the thumbnailBase64 value + */ + public byte[] getThumbnailBase64() { + return this.thumbnailBase64; + } + + /** + * Set the thumbnailBase64 value. + * + * @param withThumbnailBase64 the thumbnailBase64 value to set + */ + public void setThumbnailBase64(byte[] withThumbnailBase64) { + this.thumbnailBase64 = withThumbnailBase64; + } + +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentInfo.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentInfo.java similarity index 54% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentInfo.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentInfo.java index 829db6fb6..5dac1f9ec 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentInfo.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentInfo.java @@ -1,98 +1,88 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Metdata for an attachment. - */ -public class AttachmentInfo { - /** - * Name of the attachment. - */ - @JsonProperty(value = "name") - private String name; - - /** - * ContentType of the attachment. - */ - @JsonProperty(value = "type") - private String type; - - /** - * attachment views. - */ - @JsonProperty(value = "views") - private List views; - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the AttachmentInfo object itself. - */ - public AttachmentInfo withName(String name) { - this.name = name; - return this; - } - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the AttachmentInfo object itself. - */ - public AttachmentInfo withType(String type) { - this.type = type; - return this; - } - - /** - * Get the views value. - * - * @return the views value - */ - public List views() { - return this.views; - } - - /** - * Set the views value. - * - * @param views the views value to set - * @return the AttachmentInfo object itself. - */ - public AttachmentInfo withViews(List views) { - this.views = views; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Metdata for an attachment. + */ +public class AttachmentInfo { + /** + * Name of the attachment. + */ + @JsonProperty(value = "name") + private String name; + + /** + * ContentType of the attachment. + */ + @JsonProperty(value = "type") + private String type; + + /** + * attachment views. + */ + @JsonProperty(value = "views") + private List views; + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Set the type value. + * + * @param withType the type value to set + */ + public void setType(String withType) { + this.type = withType; + } + + /** + * Get the views value. + * + * @return the views value + */ + public List getViews() { + return this.views; + } + + /** + * Set the views value. + * + * @param withViews the views value to set + */ + public void setViews(List withViews) { + this.views = withViews; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentLayoutTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentLayoutTypes.java similarity index 68% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentLayoutTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentLayoutTypes.java index 2939adc03..b1cb74bcf 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentLayoutTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentLayoutTypes.java @@ -1,55 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for AttachmentLayoutTypes. - */ -public enum AttachmentLayoutTypes { - /** Enum value list. */ - LIST("list"), - - /** Enum value carousel. */ - CAROUSEL("carousel"); - - /** The actual serialized value for a AttachmentLayoutTypes instance. */ - private String value; - - AttachmentLayoutTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a AttachmentLayoutTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed AttachmentLayoutTypes object, or null if unable to parse. - */ - @JsonCreator - public static AttachmentLayoutTypes fromString(String value) { - AttachmentLayoutTypes[] items = AttachmentLayoutTypes.values(); - for (AttachmentLayoutTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for AttachmentLayoutTypes. + */ +public enum AttachmentLayoutTypes { + /** + * Enum value list. + */ + LIST("list"), + + /** + * Enum value carousel. + */ + CAROUSEL("carousel"); + + /** + * The actual serialized value for a AttachmentLayoutTypes instance. + */ + private String value; + + /** + * Creates a AttachmentLayoutTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + AttachmentLayoutTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a AttachmentLayoutTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed AttachmentLayoutTypes object, or null if unable to parse. + */ + @JsonCreator + public static AttachmentLayoutTypes fromString(String value) { + AttachmentLayoutTypes[] items = AttachmentLayoutTypes.values(); + for (AttachmentLayoutTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentView.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentView.java similarity index 54% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentView.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentView.java index 4bb0e0721..0a08e4917 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AttachmentView.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AttachmentView.java @@ -1,71 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Attachment View name and size. - */ -public class AttachmentView { - /** - * Id of the attachment. - */ - @JsonProperty(value = "viewId") - private String viewId; - - /** - * Size of the attachment. - */ - @JsonProperty(value = "size") - private Integer size; - - /** - * Get the viewId value. - * - * @return the viewId value - */ - public String viewId() { - return this.viewId; - } - - /** - * Set the viewId value. - * - * @param viewId the viewId value to set - * @return the AttachmentView object itself. - */ - public AttachmentView withViewId(String viewId) { - this.viewId = viewId; - return this; - } - - /** - * Get the size value. - * - * @return the size value - */ - public Integer size() { - return this.size; - } - - /** - * Set the size value. - * - * @param size the size value to set - * @return the AttachmentView object itself. - */ - public AttachmentView withSize(Integer size) { - this.size = size; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Attachment View name and size. + */ +public class AttachmentView { + /** + * Id of the attachment. + */ + @JsonProperty(value = "viewId") + private String viewId; + + /** + * Size of the attachment. + */ + @JsonProperty(value = "size") + private Integer size; + + /** + * Get the viewId value. + * + * @return the viewId value + */ + public String getViewId() { + return this.viewId; + } + + /** + * Set the viewId value. + * + * @param withViewId the viewId value to set + */ + public void setViewId(String withViewId) { + this.viewId = withViewId; + } + + /** + * Get the size value. + * + * @return the size value + */ + public Integer getSize() { + return this.size; + } + + /** + * Set the size value. + * + * @param withSize the size value to set + */ + public void setSize(Integer withSize) { + this.size = withSize; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AudioCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AudioCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java index 2f0d4aa3f..6adea2802 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/AudioCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java @@ -1,332 +1,305 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Audio card. - */ -public class AudioCard { - /** - * Title of this card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of this card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text of this card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Thumbnail placeholder. - */ - @JsonProperty(value = "image") - private ThumbnailUrl image; - - /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. - */ - @JsonProperty(value = "media") - private List media; - - /** - * Actions on this card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This content may be shared with others (default:true). - */ - @JsonProperty(value = "shareable") - private Boolean shareable; - - /** - * Should the client loop playback at end of content (default:true). - */ - @JsonProperty(value = "autoloop") - private Boolean autoloop; - - /** - * Should the client automatically start playback of media in this card - * (default:true). - */ - @JsonProperty(value = "autostart") - private Boolean autostart; - - /** - * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" - * and "4:3". - */ - @JsonProperty(value = "aspect") - private String aspect; - - /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. - */ - @JsonProperty(value = "duration") - private String duration; - - /** - * Supplementary parameter for this card. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the AudioCard object itself. - */ - public AudioCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the AudioCard object itself. - */ - public AudioCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the AudioCard object itself. - */ - public AudioCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public ThumbnailUrl image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the AudioCard object itself. - */ - public AudioCard withImage(ThumbnailUrl image) { - this.image = image; - return this; - } - - /** - * Get the media value. - * - * @return the media value - */ - public List media() { - return this.media; - } - - /** - * Set the media value. - * - * @param media the media value to set - * @return the AudioCard object itself. - */ - public AudioCard withMedia(List media) { - this.media = media; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the AudioCard object itself. - */ - public AudioCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the shareable value. - * - * @return the shareable value - */ - public Boolean shareable() { - return this.shareable; - } - - /** - * Set the shareable value. - * - * @param shareable the shareable value to set - * @return the AudioCard object itself. - */ - public AudioCard withShareable(Boolean shareable) { - this.shareable = shareable; - return this; - } - - /** - * Get the autoloop value. - * - * @return the autoloop value - */ - public Boolean autoloop() { - return this.autoloop; - } - - /** - * Set the autoloop value. - * - * @param autoloop the autoloop value to set - * @return the AudioCard object itself. - */ - public AudioCard withAutoloop(Boolean autoloop) { - this.autoloop = autoloop; - return this; - } - - /** - * Get the autostart value. - * - * @return the autostart value - */ - public Boolean autostart() { - return this.autostart; - } - - /** - * Set the autostart value. - * - * @param autostart the autostart value to set - * @return the AudioCard object itself. - */ - public AudioCard withAutostart(Boolean autostart) { - this.autostart = autostart; - return this; - } - - /** - * Get the aspect value. - * - * @return the aspect value - */ - public String aspect() { - return this.aspect; - } - - /** - * Set the aspect value. - * - * @param aspect the aspect value to set - * @return the AudioCard object itself. - */ - public AudioCard withAspect(String aspect) { - this.aspect = aspect; - return this; - } - - /** - * Gets the duration value. - */ - public String duration(){ - return this.duration; - } - - /** - * Sets the duration value. - * - * @param duration the duration value to set - * @return the AudioCard object itself. - */ - public AudioCard withDuration(String duration){ - this.duration = duration; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the AudioCard object itself. - */ - public AudioCard withValue(Object value) { - this.value = value; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Audio card. + */ +public class AudioCard { + /** + * Title of this card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of this card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text of this card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Thumbnail placeholder. + */ + @JsonProperty(value = "image") + private ThumbnailUrl image; + + /** + * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + */ + @JsonProperty(value = "media") + private List media; + + /** + * Actions on this card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This content may be shared with others (default:true). + */ + @JsonProperty(value = "shareable") + private boolean shareable; + + /** + * Should the client loop playback at end of content (default:true). + */ + @JsonProperty(value = "autoloop") + private boolean autoloop; + + /** + * Should the client automatically start playback of media in this card + * (default:true). + */ + @JsonProperty(value = "autostart") + private boolean autostart; + + /** + * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" + * and "4:3". + */ + @JsonProperty(value = "aspect") + private String aspect; + + /** + * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + */ + @JsonProperty(value = "duration") + private String duration; + + /** + * Supplementary parameter for this card. + */ + @JsonProperty(value = "value") + private Object value; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the image value. + * + * @return the image value + */ + public ThumbnailUrl getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(ThumbnailUrl withImage) { + this.image = withImage; + } + + /** + * Get the media value. + * + * @return the media value + */ + public List getMedia() { + return this.media; + } + + /** + * Set the media value. + * + * @param withMedia the media value to set + * @return the AudioCard object itself. + */ + public void setMedia(List withMedia) { + this.media = withMedia; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the shareable value. + * + * @return the shareable value + */ + public boolean getShareable() { + return this.shareable; + } + + /** + * Set the shareable value. + * + * @param withShareable the shareable value to set + */ + public void setShareable(boolean withShareable) { + this.shareable = withShareable; + } + + /** + * Get the autoloop value. + * + * @return the autoloop value + */ + public boolean getAutoloop() { + return this.autoloop; + } + + /** + * Set the autoloop value. + * + * @param withAutoloop the autoloop value to set + */ + public void setAutoloop(boolean withAutoloop) { + this.autoloop = withAutoloop; + } + + /** + * Get the autostart value. + * + * @return the autostart value + */ + public boolean getAutostart() { + return this.autostart; + } + + /** + * Set the autostart value. + * + * @param withAutostart the autostart value to set + */ + public void setAutostart(boolean withAutostart) { + this.autostart = withAutostart; + } + + /** + * Get the aspect value. + * + * @return the aspect value + */ + public String getAspect() { + return this.aspect; + } + + /** + * Set the aspect value. + * + * @param withAspect the aspect value to set + */ + public void setAspect(String withAspect) { + this.aspect = withAspect; + } + + /** + * Gets the duration value. + */ + public String getDuration() { + return this.duration; + } + + /** + * Sets the duration value. + * + * @param withDuration the duration value to set + */ + public void setDuration(String withDuration) { + this.duration = withDuration; + } + + /** + * Get the value value. + * + * @return the value value + */ + public Object getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(Object withValue) { + this.value = withValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/BasicCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/BasicCard.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/BasicCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/BasicCard.java index 2ad6f2d52..11256c0c9 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/BasicCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/BasicCard.java @@ -1,176 +1,160 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A basic card. - */ -public class BasicCard { - /** - * Title of the card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of the card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text for the card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Array of images for the card. - */ - @JsonProperty(value = "images") - private List images; - - /** - * Set of actions applicable to the current card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This action will be activated when user taps on the card itself. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the BasicCard object itself. - */ - public BasicCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the BasicCard object itself. - */ - public BasicCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the BasicCard object itself. - */ - public BasicCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the images value. - * - * @return the images value - */ - public List images() { - return this.images; - } - - /** - * Set the images value. - * - * @param images the images value to set - * @return the BasicCard object itself. - */ - public BasicCard withImages(List images) { - this.images = images; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the BasicCard object itself. - */ - public BasicCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the BasicCard object itself. - */ - public BasicCard withTap(CardAction tap) { - this.tap = tap; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A basic card. + */ +public class BasicCard { + /** + * Title of the card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of the card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text for the card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Array of images for the card. + */ + @JsonProperty(value = "images") + private List images; + + /** + * Set of actions applicable to the current card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This action will be activated when user taps on the card itself. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the images value. + * + * @return the images value + */ + public List getImages() { + return this.images; + } + + /** + * Set the images value. + * + * @param withImages the images value to set + */ + public void setImages(List withImages) { + this.images = withImages; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction tap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardAction.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java similarity index 58% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardAction.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java index ff0b46912..2a1b12976 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardAction.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java @@ -1,201 +1,184 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A clickable action. - */ -public class CardAction { - /** - * The type of action implemented by this button. Possible values include: - * 'openUrl', 'imBack', 'postBack', 'playAudio', 'playVideo', 'showImage', - * 'downloadFile', 'signin', 'call', 'payment', 'messageBack'. - */ - @JsonProperty(value = "type") - private ActionTypes type; - - /** - * Text description which appears on the button. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Image URL which will appear on the button, next to text label. - */ - @JsonProperty(value = "image") - private String image; - - /** - * Text for this action. - */ - @JsonProperty(value = "text") - private String text; - - /** - * (Optional) text to display in the chat feed if the button is clicked. - */ - @JsonProperty(value = "displayText") - private String displayText; - - /** - * Supplementary parameter for action. Content of this property depends on - * the ActionType. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * Channel-specific data associated with this action. - */ - @JsonProperty(value = "channelData") - private Object channelData; - - /** - * Get the type value. - * - * @return the type value - */ - public ActionTypes type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the CardAction object itself. - */ - public CardAction withType(ActionTypes type) { - this.type = type; - return this; - } - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the CardAction object itself. - */ - public CardAction withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public String image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the CardAction object itself. - */ - public CardAction withImage(String image) { - this.image = image; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the CardAction object itself. - */ - public CardAction withText(String text) { - this.text = text; - return this; - } - - /** - * Get the displayText value. - * - * @return the displayText value - */ - public String displayText() { - return this.displayText; - } - - /** - * Set the displayText value. - * - * @param displayText the displayText value to set - * @return the CardAction object itself. - */ - public CardAction withDisplayText(String displayText) { - this.displayText = displayText; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the CardAction object itself. - */ - public CardAction withValue(Object value) { - this.value = value; - return this; - } - - /** - * Gets the channelData value. - */ - public Object channelData(){ - return this.channelData; - } - - /** - * Sets the channelData value. - * - * @param channelData The channelData object to set. - * @return the CardAction object itself. - */ - public CardAction withChannelData(Object channelData){ - this.channelData = channelData; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A clickable action. + */ +public class CardAction { + /** + * The type of action implemented by this button. Possible values include: + * 'openUrl', 'imBack', 'postBack', 'playAudio', 'playVideo', 'showImage', + * 'downloadFile', 'signin', 'call', 'payment', 'messageBack'. + */ + @JsonProperty(value = "type") + private ActionTypes type; + + /** + * Text description which appears on the button. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Image URL which will appear on the button, next to text label. + */ + @JsonProperty(value = "image") + private String image; + + /** + * Text for this action. + */ + @JsonProperty(value = "text") + private String text; + + /** + * (Optional) text to display in the chat feed if the button is clicked. + */ + @JsonProperty(value = "displayText") + private String displayText; + + /** + * Supplementary parameter for action. Content of this property depends on + * the ActionType. + */ + @JsonProperty(value = "value") + private Object value; + + /** + * Channel-specific data associated with this action. + */ + @JsonProperty(value = "channelData") + private Object channelData; + + /** + * Get the type value. + * + * @return the type value + */ + public ActionTypes getType() { + return this.type; + } + + /** + * Set the type value. + * + * @param withType the type value to set + */ + public void setType(ActionTypes withType) { + this.type = withType; + } + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the image value. + * + * @return the image value + */ + public String getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(String withImage) { + this.image = withImage; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + * @return the CardAction object itself. + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the displayText value. + * + * @return the displayText value + */ + public String getDisplayText() { + return this.displayText; + } + + /** + * Set the displayText value. + * + * @param withDisplayText the displayText value to set + */ + public void setDisplayText(String withDisplayText) { + this.displayText = withDisplayText; + } + + /** + * Get the value value. + * + * @return the value value + */ + public Object getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(Object withValue) { + this.value = withValue; + } + + /** + * Gets the channelData value. + */ + public Object getChannelData() { + return this.channelData; + } + + /** + * Sets the channelData value. + * + * @param withChannelData The channelData object to set. + */ + public void setChannelData(Object withChannelData) { + this.channelData = withChannelData; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardImage.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardImage.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardImage.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardImage.java index 9507af95b..46c100c8e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/CardImage.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardImage.java @@ -1,97 +1,86 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An image on a card. - */ -public class CardImage { - /** - * URL thumbnail image for major content property. - */ - @JsonProperty(value = "url") - private String url; - - /** - * Image description intended for screen readers. - */ - @JsonProperty(value = "alt") - private String alt; - - /** - * Action assigned to specific Attachment. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Get the url value. - * - * @return the url value - */ - public String url() { - return this.url; - } - - /** - * Set the url value. - * - * @param url the url value to set - * @return the CardImage object itself. - */ - public CardImage withUrl(String url) { - this.url = url; - return this; - } - - /** - * Get the alt value. - * - * @return the alt value - */ - public String alt() { - return this.alt; - } - - /** - * Set the alt value. - * - * @param alt the alt value to set - * @return the CardImage object itself. - */ - public CardImage withAlt(String alt) { - this.alt = alt; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the CardImage object itself. - */ - public CardImage withTap(CardAction tap) { - this.tap = tap; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An image on a card. + */ +public class CardImage { + /** + * URL thumbnail image for major content property. + */ + @JsonProperty(value = "url") + private String url; + + /** + * Image description intended for screen readers. + */ + @JsonProperty(value = "alt") + private String alt; + + /** + * Action assigned to specific Attachment. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Get the url value. + * + * @return the url value + */ + public String getUrl() { + return this.url; + } + + /** + * Set the url value. + * + * @param withUrl the url value to set + */ + public void setUrl(String withUrl) { + this.url = withUrl; + } + + /** + * Get the alt value. + * + * @return the alt value + */ + public String getAlt() { + return this.alt; + } + + /** + * Set the alt value. + * + * @param withAlt the alt value to set + */ + public void setAlt(String withAlt) { + this.alt = withAlt; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction getTap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java new file mode 100644 index 000000000..f42945396 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java @@ -0,0 +1,190 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.HashMap; +import java.util.Map; + +/** + * Channel account information needed to route a message. + */ +public class ChannelAccount { + /** + * Channel id for the user or bot on this channel (Example: joe@smith.com, + * or @joesmith or 123456). + */ + @JsonProperty(value = "id") + private String id; + + /** + * Display friendly name. + */ + @JsonProperty(value = "name") + private String name; + + /** + * This account's object ID within Azure Active Directory (AAD). + */ + @JsonProperty(value = "aadObjectId") + private String aadObjectId; + + /** + * Role of the entity behind the account (Example: User, Bot, etc.). + * Possible values include: 'user', 'bot'. + */ + @JsonProperty(value = "role") + private RoleTypes role; + + /** + * Holds the overflow properties that aren't first class + * properties in the object. This allows extensibility + * while maintaining the object. + */ + private HashMap properties = new HashMap(); + + /** + * Initializes a new instance of the ChannelAccount class. + */ + public ChannelAccount() { + + } + + /** + * Initializes a new instance of the ChannelAccount class. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + */ + public ChannelAccount(String withId) { + this(withId, null, null, null); + } + + /** + * Initializes a new instance of the ChannelAccount class. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + * @param withName Display friendly name. + */ + public ChannelAccount(String withId, String withName) { + this(withId, withName, null, null); + } + + /** + * Initializes a new instance of the ChannelAccount class. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + * @param withName Display friendly name. + * @param withRole Role of the entity behind the account (Example User, Bot, etc.). Possible values + * include: 'user', 'bot' + */ + public ChannelAccount(String withId, String withName, RoleTypes withRole) { + this(withId, withName, withRole, null); + } + + /** + * Initializes a new instance of the ChannelAccount class. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + * @param withName Display friendly name. + * @param withRole Role of the entity behind the account (Example User, Bot, etc.). Possible values + * include: 'user', 'bot' + * @param withAadObjectId This account's object ID within Azure Active Directory (AAD). + */ + public ChannelAccount(String withId, String withName, RoleTypes withRole, String withAadObjectId) { + this.id = withId; + this.name = withName; + this.role = withRole; + this.aadObjectId = withAadObjectId; + } + + /** + * Get the {@link #role} value. + * @return the id value. + */ + public String getId() { + return this.id; + } + + /** + * Set the {@link #id} value. + * @param withId the id value to set. + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the {@link #name} value. + * @return the name value. + */ + public String getName() { + return this.name; + } + + /** + * Set the {@link #name} value. + * @param withName the name value to set. + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * Get the {@link #role} value. + * @return the role value. + */ + public RoleTypes getRole() { + return this.role; + } + + /** + * Set the {@link #role} value. + * @param withRole the role value to set. + */ + public void setRole(RoleTypes withRole) { + this.role = withRole; + } + + /** + * Overflow properties. + * Properties that are not modelled as first class properties in the object are accessible here. + * Note: A property value can be be nested. + * + * @return A Key-Value map of the properties + */ + @JsonAnyGetter + public Map getProperties() { + return this.properties; + } + + /** + * Set overflow properties. + * + * @param key Key for the property + * @param value JsonNode of value (can be nested) + */ + @JsonAnySetter + public void setProperties(String key, JsonNode value) { + this.properties.put(key, value); + } + + /** + * Gets the {@link #aadObjectId} value. + * @return The aadObjectId value. + */ + public String getAadObjectId() { + return this.aadObjectId; + } + + /** + * Sets the {@link #aadObjectId} value. + * @param withAadObjectId The aadObjectId value to set. + */ + public void setAadObjectId(String withAadObjectId) { + this.aadObjectId = withAadObjectId; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ContactRelationUpdateActionTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActionTypes.java similarity index 68% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ContactRelationUpdateActionTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActionTypes.java index 77f48dc64..8d28c0f61 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ContactRelationUpdateActionTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActionTypes.java @@ -1,55 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for ContactRelationUpdateActionTypes. - */ -public enum ContactRelationUpdateActionTypes { - /** Enum value add. */ - ADD("add"), - - /** Enum value remove. */ - REMOVE("remove"); - - /** The actual serialized value for a ContactRelationUpdateActionTypes instance. */ - private String value; - - ContactRelationUpdateActionTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ContactRelationUpdateActionTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed ContactRelationUpdateActionTypes object, or null if unable to parse. - */ - @JsonCreator - public static ContactRelationUpdateActionTypes fromString(String value) { - ContactRelationUpdateActionTypes[] items = ContactRelationUpdateActionTypes.values(); - for (ContactRelationUpdateActionTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for ContactRelationUpdateActionTypes. + */ +public enum ContactRelationUpdateActionTypes { + /** + * Enum value add. + */ + ADD("add"), + + /** + * Enum value remove. + */ + REMOVE("remove"); + + /** + * The actual serialized value for a ContactRelationUpdateActionTypes instance. + */ + private String value; + + /** + * Creates a ContactRelationUpdateActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + ContactRelationUpdateActionTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ContactRelationUpdateActionTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed ContactRelationUpdateActionTypes object, or null if unable to parse. + */ + @JsonCreator + public static ContactRelationUpdateActionTypes fromString(String value) { + ContactRelationUpdateActionTypes[] items = ContactRelationUpdateActionTypes.values(); + for (ContactRelationUpdateActionTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActivity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActivity.java deleted file mode 100644 index e31c7e8b9..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ContactRelationUpdateActivity.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.microsoft.bot.schema; - -import com.microsoft.bot.schema.models.Activity; - -public class ContactRelationUpdateActivity extends Activity { - /** - * add|remove - */ - private String _action; - - public String getAction() { - return _action; - } - - public void setAction(String action) { - this._action = action; - } -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java new file mode 100644 index 000000000..53f5e6990 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java @@ -0,0 +1,253 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Conversation account represents the identity of the conversation within a channel. + */ +public class ConversationAccount { + /** + * Indicates whether the conversation contains more than two participants + * at the time the activity was generated. The default value is false. + */ + @JsonProperty(value = "isGroup") + private boolean isGroup = false; + + /** + * Indicates the type of the conversation in channels that distinguish + * between conversation types. + */ + @JsonProperty(value = "conversationType") + private String conversationType; + + /** + * This conversation's tenant ID. + */ + @JsonProperty(value = "tenantId") + private String tenantId; + + /** + * Channel id for the user or bot on this channel (Example: joe@smith.com, + * or @joesmith or 123456). + */ + @JsonProperty(value = "id") + private String id; + + /** + * Display friendly name. + */ + @JsonProperty(value = "name") + private String name; + + /** + * This account's object ID within Azure Active Directory (AAD). + */ + @JsonProperty(value = "aadObjectId") + private String aadObjectId; + + /** + * Role of the entity behind the account (Example: User, Bot, etc.). + * Possible values include: 'user', 'bot'. + */ + @JsonProperty(value = "role") + private RoleTypes role; + + public ConversationAccount() { + + } + + /** + * Initializes a new instance of the ConversationAccount class. + * + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + */ + public ConversationAccount(String withId) { + this(false, withId, null); + } + + /** + * Initializes a new instance of the ConversationAccount class. + * + * @param withIsGroup Indicates whether the conversation contains more than two participants at the time the + * activity was. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + * @param withName Display friendly name. + */ + public ConversationAccount(boolean withIsGroup, String withId, String withName) { + this(withIsGroup, null, withId, withName, null, null, null); + } + + /** + * Initializes a new instance of the ConversationAccount class. + * + * @param withIsGroup Indicates whether the conversation contains more than two participants at the time the + * activity was. + * @param withConversationType Indicates the type of the conversation in channels that distinguish between + * conversation. + * @param withId Channel id for the user or bot on this channel (Example: joe@smith.com, or @joesmith or 123456). + * @param withName Display friendly name. + * @param withAadObjectId This account's object ID within Azure Active Directory (AAD). + * @param withRole Role of the entity behind the account (Example: User, Bot, etc.). Possible values + * include: 'user', 'bot'. + * @param withTenantId This conversation's tenant ID. + */ + public ConversationAccount(boolean withIsGroup, String withConversationType, String withId, String withName, String withAadObjectId, RoleTypes withRole, String withTenantId) { + this.isGroup = withIsGroup; + this.conversationType = withConversationType; + this.id = withId; + this.name = withName; + this.aadObjectId = withAadObjectId; + this.role = withRole; + this.tenantId = withTenantId; + } + + /** + * Get the {@link #isGroup} value. + * @return the isGroup value + */ + public boolean isGroup() { + return this.isGroup; + } + + /** + * Set the {@link #isGroup} value. + * @param withIsGroup the isGroup value to set + */ + public void setIsGroup(boolean withIsGroup) { + this.isGroup = withIsGroup; + } + + /** + * Get the {@link #conversationType} value. + * @return the conversationType value + */ + public String getConversationType() { + return this.conversationType; + } + + /** + * Set the {@link #conversationType} value. + * @param withConversationType the conversationType value to set + */ + public void setConversationType(String withConversationType) { + this.conversationType = withConversationType; + } + + /** + * Gets this conversation's {@link #tenantId}. + * @return The tenantId value. + */ + public String setTenantId() { + return this.tenantId; + } + + /** + * Sets this conversation's {@link #tenantId}. + * @param withTenantId this conversation's tenant ID + */ + public void getTenantId(String withTenantId) { + this.tenantId = withTenantId; + } + + /** + * Get the {@link #id} value. + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the {@link #id} value. + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the {@link #name} value. + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the {@link #name} value. + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } + + /** + * Gets this account's {@link #aadObjectId} within Azure Active Directory (AAD). + * @return The AAD object id. + */ + public String getAadObjectId() { + return this.aadObjectId; + } + + /** + * Sets this account's {@link #aadObjectId} within Azure Active Directory (AAD). + * @param withAadObjectId the AAD ID to set + */ + public void setAadObjectId(String withAadObjectId) { + this.aadObjectId = withAadObjectId; + } + + /** + * Get the {@link #role} value. + * @return the role value + */ + public RoleTypes getRole() { + return this.role; + } + + /** + * Set the {@link #role} value. + * @param withRole the role value to set + */ + public void setRole(RoleTypes withRole) { + this.role = withRole; + } + + /** + * Holds the overflow properties that aren't first class + * properties in the object. This allows extensibility + * while maintaining the object. + * + */ +// private HashMap properties = new HashMap(); + + /** + * Overflow properties. + * Properties that are not modelled as first class properties in the object are accessible here. + * Note: A property value can be be nested. + * + * @return A Key-Value map of the properties + */ +// @JsonAnyGetter +// public Map properties() { +// return this.properties; +// } + + /** + * Set overflow properties. + * + * @param key Key for the property + * @param value JsonNode of value (can be nested) + * + */ +// @JsonAnySetter +// public void setProperties(String key, JsonNode value) { +// this.properties.put(key, value); +// } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationMembers.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationMembers.java new file mode 100644 index 000000000..475c8c739 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationMembers.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Conversation and its members. + */ +public class ConversationMembers { + /** + * Conversation ID. + */ + @JsonProperty(value = "id") + private String id; + + /** + * List of members in this conversation. + */ + @JsonProperty(value = "members") + private List members; + + /** + * Get the {@link #id} value. + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the {@link #id} value. + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the {@link #members} value. + * @return the members value + */ + public List getMembers() { + return this.members; + } + + /** + * Set the {@link #members} value. + * @param withMembers the members value to set + */ + public void setMembers(List withMembers) { + this.members = withMembers; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationParameters.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationParameters.java new file mode 100644 index 000000000..2856e3ed5 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationParameters.java @@ -0,0 +1,171 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Parameters for creating a new conversation. + */ +public class ConversationParameters { + /** + * IsGroup. + */ + @JsonProperty(value = "isGroup") + private boolean isGroup; + + /** + * The bot address for this conversation. + */ + @JsonProperty(value = "bot") + private ChannelAccount bot; + + /** + * Members to add to the conversation. + */ + @JsonProperty(value = "members") + private List members; + + /** + * (Optional) Topic of the conversation (if supported by the channel). + */ + @JsonProperty(value = "topicName") + private String topicName; + + /** + * (Optional) The tenant ID in which the conversation should be created. + */ + @JsonProperty(value = "tenantId") + private String tenantId; + + /** + * (Optional) When creating a new conversation, use this activity as the + * intial message to the conversation. + */ + @JsonProperty(value = "activity") + private Activity activity; + + /** + * Channel specific payload for creating the conversation. + */ + @JsonProperty(value = "channelData") + private Object channelData; + + /** + * Get the {@link #isGroup} value. + * @return The isGroup value. + */ + public boolean isGroup() { + return this.isGroup; + } + + /** + * Set the {@link #isGroup} value. + * @param withIsGroup the isGroup value to set + */ + public void setIsGroup(boolean withIsGroup) { + this.isGroup = withIsGroup; + } + + /** + * Get the {@link #bot} value. + * @return The bot value. + */ + public ChannelAccount getBot() { + return this.bot; + } + + /** + * Set the {@link #bot} value. + * @param withBot the bot value to set + */ + public void setBot(ChannelAccount withBot) { + this.bot = withBot; + } + + /** + * Get the {@link #members} value. + * @return The members value. + */ + public List getMembers() { + return this.members; + } + + /** + * Set the {@link #members} value. + * @param withMembers the members value to set + */ + public void setMembers(List withMembers) { + this.members = withMembers; + } + + /** + * Get the {@link #topicName} value. + * @return The topicname value. + */ + public String getTopicName() { + return this.topicName; + } + + /** + * Set the {@link #topicName} value. + * @param withTopicName the topicName value to set + */ + public void setTopicName(String withTopicName) { + this.topicName = withTopicName; + } + + /** + * Get the {@link Activity} value. + * @return The Activity value. + */ + public Activity getActivity() { + return this.activity; + } + + /** + * Set the {@link Activity} value. + * @param withActivity the activity value to set. + */ + public void setActivity(Activity withActivity) { + this.activity = withActivity; + } + + /** + * Get the {@link #channelData} value. + * @return the channelData value. + */ + public Object getChannelData() { + return this.channelData; + } + + /** + * Set the {@link #channelData} value. + * @param withChannelData the channelData value to set + */ + public void setChannelData(Object withChannelData) { + this.channelData = withChannelData; + } + + /** + * Gets {@link #tenantId}. + * @return The tenantId value. + */ + public String getTenantId() { + return this.tenantId; + } + + /** + * Sets {@link #tenantId} value. + * @param withTenantId The tenantId value to set. + */ + public void setTenantId(String withTenantId) { + this.tenantId = withTenantId; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReference.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java similarity index 53% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReference.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java index da4b56dcd..b0ba5aa8f 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReference.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java @@ -1,176 +1,159 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An object relating to a particular point in a conversation. - */ -public class ConversationReference { - /** - * (Optional) ID of the activity to refer to. - */ - @JsonProperty(value = "activityId") - private String activityId; - - /** - * (Optional) User participating in this conversation. - */ - @JsonProperty(value = "user") - private ChannelAccount user; - - /** - * Bot participating in this conversation. - */ - @JsonProperty(value = "bot") - private ChannelAccount bot; - - /** - * Conversation reference. - */ - @JsonProperty(value = "conversation") - private ConversationAccount conversation; - - /** - * Channel ID. - */ - @JsonProperty(value = "channelId") - private String channelId; - - /** - * Service endpoint where operations concerning the referenced conversation - * may be performed. - */ - @JsonProperty(value = "serviceUrl") - private String serviceUrl; - - /** - * Get the activityId value. - * - * @return the activityId value - */ - public String activityId() { - return this.activityId; - } - - /** - * Set the activityId value. - * - * @param activityId the activityId value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withActivityId(String activityId) { - this.activityId = activityId; - return this; - } - - /** - * Get the user value. - * - * @return the user value - */ - public ChannelAccount user() { - return this.user; - } - - /** - * Set the user value. - * - * @param user the user value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withUser(ChannelAccount user) { - this.user = user; - return this; - } - - /** - * Get the bot value. - * - * @return the bot value - */ - public ChannelAccount bot() { - return this.bot; - } - - /** - * Set the bot value. - * - * @param bot the bot value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withBot(ChannelAccount bot) { - this.bot = bot; - return this; - } - - /** - * Get the conversation value. - * - * @return the conversation value - */ - public ConversationAccount conversation() { - return this.conversation; - } - - /** - * Set the conversation value. - * - * @param conversation the conversation value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withConversation(ConversationAccount conversation) { - this.conversation = conversation; - return this; - } - - /** - * Get the channelId value. - * - * @return the channelId value - */ - public String channelId() { - return this.channelId; - } - - /** - * Set the channelId value. - * - * @param channelId the channelId value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withChannelId(String channelId) { - this.channelId = channelId; - return this; - } - - /** - * Get the serviceUrl value. - * - * @return the serviceUrl value - */ - public String serviceUrl() { - return this.serviceUrl; - } - - /** - * Set the serviceUrl value. - * - * @param serviceUrl the serviceUrl value to set - * @return the ConversationReference object itself. - */ - public ConversationReference withServiceUrl(String serviceUrl) { - this.serviceUrl = serviceUrl; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An object relating to a particular point in a conversation. + */ +public class ConversationReference { + /** + * (Optional) ID of the activity to refer to. + */ + @JsonProperty(value = "activityId") + private String activityId; + + /** + * (Optional) User participating in this conversation. + */ + @JsonProperty(value = "user") + private ChannelAccount user; + + /** + * Bot participating in this conversation. + */ + @JsonProperty(value = "bot") + private ChannelAccount bot; + + /** + * Conversation reference. + */ + @JsonProperty(value = "conversation") + private ConversationAccount conversation; + + /** + * Channel ID. + */ + @JsonProperty(value = "channelId") + private String channelId; + + /** + * Service endpoint where operations concerning the referenced conversation + * may be performed. + */ + @JsonProperty(value = "serviceUrl") + private String serviceUrl; + + /** + * Get the activityId value. + * + * @return the activityId value + */ + public String getActivityId() { + return this.activityId; + } + + /** + * Set the activityId value. + * + * @param withActivityId the activityId value to set + */ + public void setActivityId(String withActivityId) { + this.activityId = withActivityId; + } + + /** + * Get the user value. + * + * @return the user value + */ + public ChannelAccount getUser() { + return this.user; + } + + /** + * Set the user value. + * + * @param withUser the user value to set + */ + public void setUser(ChannelAccount withUser) { + this.user = withUser; + } + + /** + * Get the bot value. + * + * @return the bot value + */ + public ChannelAccount getBot() { + return this.bot; + } + + /** + * Set the bot value. + * + * @param withBot the bot value to set + */ + public void setBot(ChannelAccount withBot) { + this.bot = withBot; + } + + /** + * Get the conversation value. + * + * @return the conversation value + */ + public ConversationAccount getConversation() { + return this.conversation; + } + + /** + * Set the conversation value. + * + * @param withConversation the conversation value to set + */ + public void setConversation(ConversationAccount withConversation) { + this.conversation = withConversation; + } + + /** + * Get the channelId value. + * + * @return the channelId value + */ + public String getChannelId() { + return this.channelId; + } + + /** + * Set the channelId value. + * + * @param withChannelId the channelId value to set + */ + public void setChannelId(String withChannelId) { + this.channelId = withChannelId; + } + + /** + * Get the serviceUrl value. + * + * @return the serviceUrl value + */ + public String getServiceUrl() { + return this.serviceUrl; + } + + /** + * Set the serviceUrl value. + * + * @param withServiceUrl the serviceUrl value to set + */ + public void setServiceUrl(String withServiceUrl) { + this.serviceUrl = withServiceUrl; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReferenceHelper.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReferenceHelper.java new file mode 100644 index 000000000..379b616ac --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReferenceHelper.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import java.util.UUID; + +public class ConversationReferenceHelper { + private ConversationReference reference; + + public ConversationReferenceHelper(ConversationReference withReference) { + this.reference = withReference; + } + + /** + * Creates {@link Activity} from conversation reference as it is posted to bot. + */ + public Activity getPostToBotMessage() { + Activity activity = new Activity(); + activity.setType(ActivityTypes.MESSAGE); + activity.setId(UUID.randomUUID().toString()); + activity.setRecipient(new ChannelAccount( + reference.getBot().getId(), + reference.getBot().getName())); + activity.setChannelId(reference.getChannelId()); + activity.setServiceUrl(reference.getServiceUrl()); + activity.setConversation(new ConversationAccount( + reference.getConversation().isGroup(), + reference.getConversation().getId(), + reference.getConversation().getName())); + activity.setFrom(new ChannelAccount( + reference.getUser().getId(), + reference.getUser().getName())); + + return activity; + } + + /** + * Creates {@link Activity} from conversation reference that can be posted to user as reply. + */ + public Activity getPostToUserMessage() { + Activity msg = this.getPostToBotMessage(); + + // swap from and recipient + msg.setFrom(msg.getRecipient()); + msg.setRecipient(msg.getFrom()); + + return msg; + } +} + + diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationResourceResponse.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationResourceResponse.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationResourceResponse.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationResourceResponse.java index 9d6cf8b1e..749a352cf 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationResourceResponse.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationResourceResponse.java @@ -1,98 +1,87 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A response containing a resource. - */ -public class ConversationResourceResponse { - /** - * ID of the Activity (if sent). - */ - @JsonProperty(value = "activityId") - private String activityId; - - /** - * Service endpoint where operations concerning the conversation may be - * performed. - */ - @JsonProperty(value = "serviceUrl") - private String serviceUrl; - - /** - * Id of the resource. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Get the activityId value. - * - * @return the activityId value - */ - public String activityId() { - return this.activityId; - } - - /** - * Set the activityId value. - * - * @param activityId the activityId value to set - * @return the ConversationResourceResponse object itself. - */ - public ConversationResourceResponse withActivityId(String activityId) { - this.activityId = activityId; - return this; - } - - /** - * Get the serviceUrl value. - * - * @return the serviceUrl value - */ - public String serviceUrl() { - return this.serviceUrl; - } - - /** - * Set the serviceUrl value. - * - * @param serviceUrl the serviceUrl value to set - * @return the ConversationResourceResponse object itself. - */ - public ConversationResourceResponse withServiceUrl(String serviceUrl) { - this.serviceUrl = serviceUrl; - return this; - } - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the ConversationResourceResponse object itself. - */ - public ConversationResourceResponse withId(String id) { - this.id = id; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A response containing a resource. + */ +public class ConversationResourceResponse { + /** + * ID of the Activity (if sent). + */ + @JsonProperty(value = "activityId") + private String activityId; + + /** + * Service endpoint where operations concerning the conversation may be + * performed. + */ + @JsonProperty(value = "serviceUrl") + private String serviceUrl; + + /** + * Id of the resource. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Get the activityId value. + * + * @return the activityId value + */ + public String getActivityId() { + return this.activityId; + } + + /** + * Set the activityId value. + * + * @param withActivityId the activityId value to set + */ + public void setActivityId(String withActivityId) { + this.activityId = withActivityId; + } + + /** + * Get the serviceUrl value. + * + * @return the serviceUrl value + */ + public String getServiceUrl() { + return this.serviceUrl; + } + + /** + * Set the serviceUrl value. + * + * @param withServiceUrl the serviceUrl value to set + */ + public void setServiceUrl(String withServiceUrl) { + this.serviceUrl = withServiceUrl; + } + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationsResult.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationsResult.java similarity index 52% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationsResult.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationsResult.java index 35e4151da..c2faa0d0e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationsResult.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationsResult.java @@ -1,72 +1,64 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Conversations result. - */ -public class ConversationsResult { - /** - * Paging token. - */ - @JsonProperty(value = "continuationToken") - private String continuationToken; - - /** - * List of conversations. - */ - @JsonProperty(value = "conversations") - private List conversations; - - /** - * Get the continuationToken value. - * - * @return the continuationToken value - */ - public String continuationToken() { - return this.continuationToken; - } - - /** - * Set the continuationToken value. - * - * @param continuationToken the continuationToken value to set - * @return the ConversationsResult object itself. - */ - public ConversationsResult withContinuationToken(String continuationToken) { - this.continuationToken = continuationToken; - return this; - } - - /** - * Get the conversations value. - * - * @return the conversations value - */ - public List conversations() { - return this.conversations; - } - - /** - * Set the conversations value. - * - * @param conversations the conversations value to set - * @return the ConversationsResult object itself. - */ - public ConversationsResult withConversations(List conversations) { - this.conversations = conversations; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Conversations result. + */ +public class ConversationsResult { + /** + * Paging token. + */ + @JsonProperty(value = "continuationToken") + private String continuationToken; + + /** + * List of conversations. + */ + @JsonProperty(value = "conversations") + private List conversations; + + /** + * Get the continuationToken value. + * + * @return the continuationToken value + */ + public String getContinuationToken() { + return this.continuationToken; + } + + /** + * Set the continuationToken value. + * + * @param withContinuationToken the continuationToken value to set + */ + public void setContinuationToken(String withContinuationToken) { + this.continuationToken = withContinuationToken; + } + + /** + * Get the conversations value. + * + * @return the conversations value + */ + public List getConversations() { + return this.conversations; + } + + /** + * Set the conversations value. + * + * @param withConversations the conversations value to set + */ + public void setConversations(List withConversations) { + this.conversations = withConversations; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/DeliveryModes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/DeliveryModes.java similarity index 68% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/DeliveryModes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/DeliveryModes.java index c0a7ca285..50bfb1840 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/DeliveryModes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/DeliveryModes.java @@ -1,56 +1,63 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Values for deliveryMode field. - */ -public enum DeliveryModes { - /** Enum value normal. */ - NORMAL("normal"), - - /** Enum value notification. */ - NOTIFICATION("notification"); - - - /** The actual serialized value for a DeliveryModes instance. */ - private String value; - - DeliveryModes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ActivityTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed ActivityTypes object, or null if unable to parse. - */ - @JsonCreator - public static DeliveryModes fromString(String value) { - DeliveryModes[] items = DeliveryModes.values(); - for (DeliveryModes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Values for deliveryMode field. + */ +public enum DeliveryModes { + /** + * Enum value normal. + */ + NORMAL("normal"), + + /** + * Enum value notification. + */ + NOTIFICATION("notification"); + + + /** + * The actual serialized value for a DeliveryModes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + DeliveryModes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ActivityTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed ActivityTypes object, or null if unable to parse. + */ + @JsonCreator + public static DeliveryModes fromString(String value) { + DeliveryModes[] items = DeliveryModes.values(); + for (DeliveryModes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/EndOfConversationCodes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EndOfConversationCodes.java similarity index 64% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/EndOfConversationCodes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EndOfConversationCodes.java index 43b9fbf47..efb8f9b18 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/EndOfConversationCodes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EndOfConversationCodes.java @@ -1,67 +1,82 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for EndOfConversationCodes. - */ -public enum EndOfConversationCodes { - /** Enum value unknown. */ - UNKNOWN("unknown"), - - /** Enum value completedSuccessfully. */ - COMPLETED_SUCCESSFULLY("completedSuccessfully"), - - /** Enum value userCancelled. */ - USER_CANCELLED("userCancelled"), - - /** Enum value botTimedOut. */ - BOT_TIMED_OUT("botTimedOut"), - - /** Enum value botIssuedInvalidMessage. */ - BOT_ISSUED_INVALID_MESSAGE("botIssuedInvalidMessage"), - - /** Enum value channelFailed. */ - CHANNEL_FAILED("channelFailed"); - - /** The actual serialized value for a EndOfConversationCodes instance. */ - private String value; - - EndOfConversationCodes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a EndOfConversationCodes instance. - * - * @param value the serialized value to parse. - * @return the parsed EndOfConversationCodes object, or null if unable to parse. - */ - @JsonCreator - public static EndOfConversationCodes fromString(String value) { - EndOfConversationCodes[] items = EndOfConversationCodes.values(); - for (EndOfConversationCodes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for EndOfConversationCodes. + */ +public enum EndOfConversationCodes { + /** + * Enum value unknown. + */ + UNKNOWN("unknown"), + + /** + * Enum value completedSuccessfully. + */ + COMPLETED_SUCCESSFULLY("completedSuccessfully"), + + /** + * Enum value userCancelled. + */ + USER_CANCELLED("userCancelled"), + + /** + * Enum value botTimedOut. + */ + BOT_TIMED_OUT("botTimedOut"), + + /** + * Enum value botIssuedInvalidMessage. + */ + BOT_ISSUED_INVALID_MESSAGE("botIssuedInvalidMessage"), + + /** + * Enum value channelFailed. + */ + CHANNEL_FAILED("channelFailed"); + + /** + * The actual serialized value for a EndOfConversationCodes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + EndOfConversationCodes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a EndOfConversationCodes instance. + * + * @param value the serialized value to parse. + * @return the parsed EndOfConversationCodes object, or null if unable to parse. + */ + @JsonCreator + public static EndOfConversationCodes fromString(String value) { + EndOfConversationCodes[] items = EndOfConversationCodes.values(); + for (EndOfConversationCodes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntityImpl.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntityImpl.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java index e8ebd2104..18e06d130 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntityImpl.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java @@ -1,146 +1,132 @@ -package com.microsoft.bot.schema; - - - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.microsoft.bot.schema.models.Entity; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - - - -public class EntityImpl extends Entity { - private ObjectMapper objectMapper = new ObjectMapper(); - - /** - * Initializes a new instance of the Entity class. - */ - public EntityImpl() { - CustomInit(); - } - - - /** - * Initializes a new instance of the Entity class. - * @param type Entity Type (typically from schema.org - * types) - */ - public EntityImpl(String type) { - this.type = type; - CustomInit(); - } - - /** - * An initialization method that performs custom operations like setting defaults - */ - void CustomInit() { - } - /** - * Gets or sets entity Type (typically from schema.org types) - */ - public String type; - - - /** - * @return - */ - private HashMap properties = new HashMap(); - - @JsonAnyGetter - public Map properties() { - - return this.properties; - - } - - - @JsonAnySetter - public void setProperties(String key, JsonNode value) { - this.properties.put(key, value); - } - - - /** - */ - - /** - * Retrieve internal payload. - */ - - /** - */ - - /** - * @param T - */ - - /** - * @return - */ - - public T GetAs(Class type) { - - // Serialize - String tempJson; - try { - tempJson = objectMapper.writeValueAsString(this); - } catch (JsonProcessingException e) { - e.printStackTrace(); - return null; - } - - // Deserialize - T newObj = null; - try { - newObj = (T) objectMapper.readValue(tempJson, type); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - - return newObj; - - - } - - - /** - * Set internal payload. - * @param T - * @param obj - */ - - public boolean SetAs(T obj) { - // Serialize - String tempJson; - try { - tempJson = objectMapper.writeValueAsString(obj); - } catch (JsonProcessingException e) { - e.printStackTrace(); - return false; - } - - EntityImpl tempEntity; - try { - tempEntity = objectMapper.readValue(tempJson, EntityImpl.class); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - for (Map.Entry entry : tempEntity.properties.entrySet()) { - this.properties.put(entry.getKey(), entry.getValue()); - } - this.type = obj.getClass().getTypeName(); - - return true; - - } -} - +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Metadata object pertaining to an activity. + */ +public class Entity { + private ObjectMapper objectMapper = new ObjectMapper(); + + /** + */ + private HashMap properties = new HashMap(); + + /** + * Type of this entity (RFC 3987 IRI). + */ + @JsonProperty(value = "type") + private String type; + + /** + * Get the {@link #type} value. + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Set the {@link #type} value. + * @param withType the type value to set + */ + public void setType(String withType) { + this.type = withType; + } + + /** + * @see #properties + */ + @JsonAnyGetter + public Map getProperties() { + return this.properties; + } + + /** + * @see #properties + */ + @JsonAnySetter + public void setProperties(String key, JsonNode value) { + this.properties.put(key, value); + } + + /** + * Retrieve internal payload. + * + * @param classType of type T + * @return + */ + public T getAs(Class classType) { + + // Serialize + String tempJson; + try { + tempJson = objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return null; + } + + // Deserialize + T newObj = null; + try { + newObj = objectMapper.readValue(tempJson, classType); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + return newObj; + } + + /** + * Set internal payload. + * + * This is only intended to be used with other Enitity classes: + * @see Mention + * @see Place + * @see GeoCoordinates + * + * @param obj of type T + * @param obj + */ + public Entity setAs(T obj) { + // Serialize + String tempJson; + try { + tempJson = objectMapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException(e); + } + + Entity tempEntity; + try { + tempEntity = objectMapper.readValue(tempJson, Entity.class); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + + for (Map.Entry entry : tempEntity.properties.entrySet()) { + this.properties.put(entry.getKey(), entry.getValue()); + } + + this.type = tempEntity.getType(); + + return this; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntitySerialization.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntitySerialization.java new file mode 100644 index 000000000..3e08d75e3 --- /dev/null +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/EntitySerialization.java @@ -0,0 +1,10 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +public interface EntitySerialization { +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Error.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Error.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Error.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Error.java index a5ece49f1..66bec01a1 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Error.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Error.java @@ -1,91 +1,82 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Object representing error information. - */ -public class Error { - /** - * Error code. - */ - @JsonProperty(value = "code") - private String code; - - /** - * Error message. - */ - @JsonProperty(value = "message") - private String message; - - /** - * Error from inner http call - */ - @JsonProperty(value = "innerHttpError") - private InnerHttpError innerHttpError; - - /** - * Get the code value. - * - * @return the code value - */ - public String code() { - return this.code; - } - - /** - * Set the code value. - * - * @param code the code value to set - * @return the Error object itself. - */ - public Error withCode(String code) { - this.code = code; - return this; - } - - /** - * Get the message value. - * - * @return the message value - */ - public String message() { - return this.message; - } - - /** - * Set the message value. - * - * @param message the message value to set - * @return the Error object itself. - */ - public Error withMessage(String message) { - this.message = message; - return this; - } - - /** - * Gets error from inner http call. - */ - public InnerHttpError innerHttpError(){ - return this.innerHttpError; - } - - /** - * Sets error from inner http call. - */ - public Error withInnerHttpError(InnerHttpError innerHttpError){ - this.innerHttpError = innerHttpError; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Object representing error information. + */ +public class Error { + /** + * Error code. + */ + @JsonProperty(value = "code") + private String code; + + /** + * Error message. + */ + @JsonProperty(value = "message") + private String message; + + /** + * Error from inner http call + */ + @JsonProperty(value = "innerHttpError") + private InnerHttpError innerHttpError; + + /** + * Get the code value. + * + * @return the code value + */ + public String getCode() { + return this.code; + } + + /** + * Set the code value. + * + * @param withCode the code value to set + */ + public void setCode(String withCode) { + this.code = withCode; + } + + /** + * Get the message value. + * + * @return the message value + */ + public String getMessage() { + return this.message; + } + + /** + * Set the message value. + * + * @param withMessage the message value to set + */ + public void setMessage(String withMessage) { + this.message = withMessage; + } + + /** + * Gets error from inner http call. + */ + public InnerHttpError getInnerHttpError() { + return this.innerHttpError; + } + + /** + * Sets error from inner http call. + */ + public void setInnerHttpError(InnerHttpError withInnerHttpError) { + this.innerHttpError = withInnerHttpError; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ErrorResponse.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ErrorResponse.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ErrorResponse.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ErrorResponse.java index ae3f0fd80..5057d6998 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ErrorResponse.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ErrorResponse.java @@ -1,45 +1,46 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An HTTP API response. - */ -public class ErrorResponse { - /** - * Error message. - */ - @JsonProperty(value = "error") - private Error error; - - /** - * Get the error value. - * - * @return the error value - */ - public Error error() { - return this.error; - } - - /** - * Set the error value. - * - * @param error the error value to set - * @return the ErrorResponse object itself. - */ - public ErrorResponse withError(Error error) { - this.error = error; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An HTTP API response. + */ +public class ErrorResponse { + public ErrorResponse() { + + } + + /** + * Error message. + */ + @JsonProperty(value = "error") + private Error error; + + public ErrorResponse(Error withError) { + this.error = withError; + } + + /** + * Get the error value. + * + * @return the error value + */ + public Error getError() { + return this.error; + } + + /** + * Set the error value. + * + * @param withError the error value to set + */ + public void setError(Error withError) { + this.error = withError; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Fact.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Fact.java similarity index 61% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Fact.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Fact.java index 2793cc6e2..f2c6dab0d 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Fact.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Fact.java @@ -1,74 +1,65 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Set of key-value pairs. Advantage of this section is that key and value - * properties will be - * rendered with default style information with some delimiter between them. So - * there is no need for developer to specify style information. - */ -public class Fact { - /** - * The key for this Fact. - */ - @JsonProperty(value = "key") - private String key; - - /** - * The value for this Fact. - */ - @JsonProperty(value = "value") - private String value; - - /** - * Get the key value. - * - * @return the key value - */ - public String key() { - return this.key; - } - - /** - * Set the key value. - * - * @param key the key value to set - * @return the Fact object itself. - */ - public Fact withKey(String key) { - this.key = key; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public String value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the Fact object itself. - */ - public Fact withValue(String value) { - this.value = value; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Set of key-value pairs. Advantage of this section is that key and value + * properties will be + * rendered with default style information with some delimiter between them. So + * there is no need for developer to specify style information. + */ +public class Fact { + /** + * The key for this Fact. + */ + @JsonProperty(value = "key") + private String key; + + /** + * The value for this Fact. + */ + @JsonProperty(value = "value") + private String value; + + /** + * Get the key value. + * + * @return the key value + */ + public String getKey() { + return this.key; + } + + /** + * Set the key value. + * + * @param withKey the key value to set + */ + public void setKey(String withKey) { + this.key = withKey; + } + + /** + * Get the value value. + * + * @return the value value + */ + public String getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(String withValue) { + this.value = withValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/GeoCoordinates.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/GeoCoordinates.java similarity index 53% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/GeoCoordinates.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/GeoCoordinates.java index 3973c555c..353034761 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/GeoCoordinates.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/GeoCoordinates.java @@ -1,149 +1,132 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.microsoft.bot.schema.EntityImpl; - -/** - * GeoCoordinates (entity type: "https://schema.org/GeoCoordinates"). - */ -public class GeoCoordinates extends EntityImpl { - /** - * Elevation of the location [WGS - * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). - */ - @JsonProperty(value = "elevation") - private Double elevation; - - /** - * Latitude of the location [WGS - * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). - */ - @JsonProperty(value = "latitude") - private Double latitude; - - /** - * Longitude of the location [WGS - * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). - */ - @JsonProperty(value = "longitude") - private Double longitude; - - /** - * The type of the thing. - */ - @JsonProperty(value = "type") - private String type; - - /** - * The name of the thing. - */ - @JsonProperty(value = "name") - private String name; - - /** - * Get the elevation value. - * - * @return the elevation value - */ - public Double elevation() { - return this.elevation; - } - - /** - * Set the elevation value. - * - * @param elevation the elevation value to set - * @return the GeoCoordinates object itself. - */ - public GeoCoordinates withElevation(Double elevation) { - this.elevation = elevation; - return this; - } - - /** - * Get the latitude value. - * - * @return the latitude value - */ - public Double latitude() { - return this.latitude; - } - - /** - * Set the latitude value. - * - * @param latitude the latitude value to set - * @return the GeoCoordinates object itself. - */ - public GeoCoordinates withLatitude(Double latitude) { - this.latitude = latitude; - return this; - } - - /** - * Get the longitude value. - * - * @return the longitude value - */ - public Double longitude() { - return this.longitude; - } - - /** - * Set the longitude value. - * - * @param longitude the longitude value to set - * @return the GeoCoordinates object itself. - */ - public GeoCoordinates withLongitude(Double longitude) { - this.longitude = longitude; - return this; - } - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the GeoCoordinates object itself. - */ - public GeoCoordinates withType(String type) { - this.type = type; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the GeoCoordinates object itself. - */ - public GeoCoordinates withName(String name) { - this.name = name; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * GeoCoordinates (entity type: "https://schema.org/GeoCoordinates"). + */ +public class GeoCoordinates implements EntitySerialization { + /** + * Elevation of the location [WGS + * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). + */ + @JsonProperty(value = "elevation") + private double elevation; + + /** + * Latitude of the location [WGS + * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). + */ + @JsonProperty(value = "latitude") + private double latitude; + + /** + * Longitude of the location [WGS + * 84](https://en.wikipedia.org/wiki/World_Geodetic_System). + */ + @JsonProperty(value = "longitude") + private double longitude; + + /** + * The type of the thing. + */ + @JsonProperty(value = "type") + private String type; + + /** + * The name of the thing. + */ + @JsonProperty(value = "name") + private String name; + + public GeoCoordinates() { + this.type = "GeoCoordinates"; + } + + /** + * Get the elevation value. + * + * @return the elevation value + */ + public Double getElevation() { + return this.elevation; + } + + /** + * Set the elevation value. + * + * @param withElevation the elevation value to set + */ + public void setElevation(double withElevation) { + this.elevation = withElevation; + } + + /** + * Get the latitude value. + * + * @return the latitude value + */ + public double getLatitude() { + return this.latitude; + } + + /** + * Set the latitude value. + * + * @param withLatitude the latitude value to set + */ + public void setLatitude(double withLatitude) { + this.latitude = withLatitude; + } + + /** + * Get the longitude value. + * + * @return the longitude value + */ + public double getLongitude() { + return this.longitude; + } + + /** + * Set the longitude value. + * + * @param withLongitude the longitude value to set + */ + public void setLongitude(double withLongitude) { + this.longitude = withLongitude; + } + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/HeroCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/HeroCard.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/HeroCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/HeroCard.java index 15e8d28e1..f7d5d7151 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/HeroCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/HeroCard.java @@ -1,176 +1,160 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A Hero card (card with a single, large image). - */ -public class HeroCard { - /** - * Title of the card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of the card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text for the card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Array of images for the card. - */ - @JsonProperty(value = "images") - private List images; - - /** - * Set of actions applicable to the current card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This action will be activated when user taps on the card itself. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the HeroCard object itself. - */ - public HeroCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the HeroCard object itself. - */ - public HeroCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the HeroCard object itself. - */ - public HeroCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the images value. - * - * @return the images value - */ - public List images() { - return this.images; - } - - /** - * Set the images value. - * - * @param images the images value to set - * @return the HeroCard object itself. - */ - public HeroCard withImages(List images) { - this.images = images; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the HeroCard object itself. - */ - public HeroCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the HeroCard object itself. - */ - public HeroCard withTap(CardAction tap) { - this.tap = tap; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A Hero card (card with a single, large image). + */ +public class HeroCard { + /** + * Title of the card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of the card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text for the card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Array of images for the card. + */ + @JsonProperty(value = "images") + private List images; + + /** + * Set of actions applicable to the current card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This action will be activated when user taps on the card itself. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the images value. + * + * @return the images value + */ + public List getImages() { + return this.images; + } + + /** + * Set the images value. + * + * @param withImages the images value to set + */ + public void setImages(List withImages) { + this.images = withImages; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction getTap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InnerHttpError.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InnerHttpError.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InnerHttpError.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InnerHttpError.java index 4bb294d67..d9cf25980 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InnerHttpError.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InnerHttpError.java @@ -1,66 +1,58 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Object representing inner http error. - */ -public class InnerHttpError { - /** - * HttpStatusCode from failed request. - */ - @JsonProperty(value = "statusCode") - private int statusCode; - - /** - * Body from failed request. - */ - @JsonProperty(value = "body") - private Object body; - - /** - * Gets HttpStatusCode from failed request. - * - * @return the statusCode value - */ - public int statusCode() { - return this.statusCode; - } - - /** - * Sets HttpStatusCode from failed request. - * - * @param activities the activities value to set - * @return the InnerHttpError object itself. - */ - public InnerHttpError withStatusCode(int statusCode) { - this.statusCode = statusCode; - return this; - } - - /** - * Gets Body from failed request. - */ - public Object body(){ - return this.body; - } - - /** - * Sets Body from failed request. - * @param body The body to set - */ - public InnerHttpError withBody(Object body){ - this.body = body; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Object representing inner http error. + */ +public class InnerHttpError { + /** + * HttpStatusCode from failed request. + */ + @JsonProperty(value = "statusCode") + private int statusCode; + + /** + * Body from failed request. + */ + @JsonProperty(value = "body") + private Object body; + + /** + * Gets HttpStatusCode from failed request. + * + * @return the statusCode value + */ + public int getStatusCode() { + return this.statusCode; + } + + /** + * Sets HttpStatusCode from failed request. + * + * @param withStatusCode + */ + public void setStatusCode(int withStatusCode) { + this.statusCode = withStatusCode; + } + + /** + * Gets Body from failed request. + */ + public Object getBody() { + return this.body; + } + + /** + * Sets Body from failed request. + */ + public void setBody(Object withBody) { + this.body = withBody; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InputHints.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InputHints.java similarity index 66% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InputHints.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InputHints.java index 847f836f3..026f1a254 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InputHints.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InputHints.java @@ -1,58 +1,67 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for InputHints. - */ -public enum InputHints { - /** Enum value acceptingInput. */ - ACCEPTING_INPUT("acceptingInput"), - - /** Enum value ignoringInput. */ - IGNORING_INPUT("ignoringInput"), - - /** Enum value expectingInput. */ - EXPECTING_INPUT("expectingInput"); - - /** The actual serialized value for a InputHints instance. */ - private String value; - - InputHints(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a InputHints instance. - * - * @param value the serialized value to parse. - * @return the parsed InputHints object, or null if unable to parse. - */ - @JsonCreator - public static InputHints fromString(String value) { - InputHints[] items = InputHints.values(); - for (InputHints item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for InputHints. + */ +public enum InputHints { + /** + * Enum value acceptingInput. + */ + ACCEPTING_INPUT("acceptingInput"), + + /** + * Enum value ignoringInput. + */ + IGNORING_INPUT("ignoringInput"), + + /** + * Enum value expectingInput. + */ + EXPECTING_INPUT("expectingInput"); + + /** + * The actual serialized value for a InputHints instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + InputHints(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a InputHints instance. + * + * @param value the serialized value to parse. + * @return the parsed InputHints object, or null if unable to parse. + */ + @JsonCreator + public static InputHints fromString(String value) { + InputHints[] items = InputHints.values(); + for (InputHints item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InstallationUpdateActionTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InstallationUpdateActionTypes.java similarity index 69% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InstallationUpdateActionTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InstallationUpdateActionTypes.java index 5b5c70add..09bf2fba8 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/InstallationUpdateActionTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/InstallationUpdateActionTypes.java @@ -1,55 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for InstallationUpdateActionTypes. - */ -public enum InstallationUpdateActionTypes { - /** Enum value add. */ - ADD("add"), - - /** Enum value remove. */ - REMOVE("remove"); - - /** The actual serialized value for a InstallationUpdateActionTypes instance. */ - private String value; - - InstallationUpdateActionTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a InstallationUpdateActionTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed InstallationUpdateActionTypes object, or null if unable to parse. - */ - @JsonCreator - public static InstallationUpdateActionTypes fromString(String value) { - InstallationUpdateActionTypes[] items = InstallationUpdateActionTypes.values(); - for (InstallationUpdateActionTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for InstallationUpdateActionTypes. + */ +public enum InstallationUpdateActionTypes { + /** + * Enum value add. + */ + ADD("add"), + + /** + * Enum value remove. + */ + REMOVE("remove"); + + /** + * The actual serialized value for a InstallationUpdateActionTypes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + InstallationUpdateActionTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a InstallationUpdateActionTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed InstallationUpdateActionTypes object, or null if unable to parse. + */ + @JsonCreator + public static InstallationUpdateActionTypes fromString(String value) { + InstallationUpdateActionTypes[] items = InstallationUpdateActionTypes.values(); + for (InstallationUpdateActionTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java index 9a54ce6b1..19ff7cbbc 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java @@ -1,332 +1,304 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Media card. - */ -public class MediaCard { - /** - * Title of this card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of this card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text of this card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Thumbnail placeholder. - */ - @JsonProperty(value = "image") - private ThumbnailUrl image; - - /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. - */ - @JsonProperty(value = "media") - private List media; - - /** - * Actions on this card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This content may be shared with others (default:true). - */ - @JsonProperty(value = "shareable") - private Boolean shareable; - - /** - * Should the client loop playback at end of content (default:true). - */ - @JsonProperty(value = "autoloop") - private Boolean autoloop; - - /** - * Should the client automatically start playback of media in this card - * (default:true). - */ - @JsonProperty(value = "autostart") - private Boolean autostart; - - /** - * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" - * and "4:3". - */ - @JsonProperty(value = "aspect") - private String aspect; - - /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. - */ - @JsonProperty(value = "duration") - private String duration; - - /** - * Supplementary parameter for this card. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the MediaCard object itself. - */ - public MediaCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the MediaCard object itself. - */ - public MediaCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the MediaCard object itself. - */ - public MediaCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public ThumbnailUrl image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the MediaCard object itself. - */ - public MediaCard withImage(ThumbnailUrl image) { - this.image = image; - return this; - } - - /** - * Get the media value. - * - * @return the media value - */ - public List media() { - return this.media; - } - - /** - * Set the media value. - * - * @param media the media value to set - * @return the MediaCard object itself. - */ - public MediaCard withMedia(List media) { - this.media = media; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the MediaCard object itself. - */ - public MediaCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the shareable value. - * - * @return the shareable value - */ - public Boolean shareable() { - return this.shareable; - } - - /** - * Set the shareable value. - * - * @param shareable the shareable value to set - * @return the MediaCard object itself. - */ - public MediaCard withShareable(Boolean shareable) { - this.shareable = shareable; - return this; - } - - /** - * Get the autoloop value. - * - * @return the autoloop value - */ - public Boolean autoloop() { - return this.autoloop; - } - - /** - * Set the autoloop value. - * - * @param autoloop the autoloop value to set - * @return the MediaCard object itself. - */ - public MediaCard withAutoloop(Boolean autoloop) { - this.autoloop = autoloop; - return this; - } - - /** - * Get the autostart value. - * - * @return the autostart value - */ - public Boolean autostart() { - return this.autostart; - } - - /** - * Set the autostart value. - * - * @param autostart the autostart value to set - * @return the MediaCard object itself. - */ - public MediaCard withAutostart(Boolean autostart) { - this.autostart = autostart; - return this; - } - - /** - * Get the aspect value. - * - * @return the aspect value - */ - public String aspect() { - return this.aspect; - } - - /** - * Set the aspect value. - * - * @param aspect the aspect value to set - * @return the MediaCard object itself. - */ - public MediaCard withAspect(String aspect) { - this.aspect = aspect; - return this; - } - - /** - * Gets the duration value. - */ - public String duration(){ - return this.duration; - } - - /** - * Sets the duration value. - * - * @param duration the duration value to set - * @return the MediaCard object itself. - */ - public MediaCard withDuration(String duration){ - this.duration = duration; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the MediaCard object itself. - */ - public MediaCard withValue(Object value) { - this.value = value; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Media card. + */ +public class MediaCard { + /** + * Title of this card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of this card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text of this card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Thumbnail placeholder. + */ + @JsonProperty(value = "image") + private ThumbnailUrl image; + + /** + * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + */ + @JsonProperty(value = "media") + private List media; + + /** + * Actions on this card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This content may be shared with others (default:true). + */ + @JsonProperty(value = "shareable") + private boolean shareable; + + /** + * Should the client loop playback at end of content (default:true). + */ + @JsonProperty(value = "autoloop") + private boolean autoloop; + + /** + * Should the client automatically start playback of media in this card + * (default:true). + */ + @JsonProperty(value = "autostart") + private boolean autostart; + + /** + * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" + * and "4:3". + */ + @JsonProperty(value = "aspect") + private String aspect; + + /** + * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + */ + @JsonProperty(value = "duration") + private String duration; + + /** + * Supplementary parameter for this card. + */ + @JsonProperty(value = "value") + private Object value; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the image value. + * + * @return the image value + */ + public ThumbnailUrl getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(ThumbnailUrl withImage) { + this.image = withImage; + } + + /** + * Get the media value. + * + * @return the media value + */ + public List getMedia() { + return this.media; + } + + /** + * Set the media value. + * + * @param withMedia the media value to set + */ + public void setMedia(List withMedia) { + this.media = withMedia; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the shareable value. + * + * @return the shareable value + */ + public boolean getShareable() { + return this.shareable; + } + + /** + * Set the shareable value. + * + * @param withShareable the shareable value to set + */ + public void setShareable(boolean withShareable) { + this.shareable = withShareable; + } + + /** + * Get the autoloop value. + * + * @return the autoloop value + */ + public boolean getAutoloop() { + return this.autoloop; + } + + /** + * Set the autoloop value. + * + * @param withAutoloop the autoloop value to set + */ + public void setAutoloop(boolean withAutoloop) { + this.autoloop = withAutoloop; + } + + /** + * Get the autostart value. + * + * @return the autostart value + */ + public boolean getAutostart() { + return this.autostart; + } + + /** + * Set the autostart value. + * + * @param withAutostart the autostart value to set + */ + public void setAutostart(boolean withAutostart) { + this.autostart = withAutostart; + } + + /** + * Get the aspect value. + * + * @return the aspect value + */ + public String getAspect() { + return this.aspect; + } + + /** + * Set the aspect value. + * + * @param withAspect the aspect value to set + */ + public void setAspect(String withAspect) { + this.aspect = withAspect; + } + + /** + * Gets the duration value. + */ + public String getDuration() { + return this.duration; + } + + /** + * Sets the duration value. + * + * @param withDuration the duration value to set + */ + public void setDuration(String withDuration) { + this.duration = withDuration; + } + + /** + * Get the value value. + * + * @return the value value + */ + public Object getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(Object withValue) { + this.value = withValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaEventValue.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaEventValue.java similarity index 58% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaEventValue.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaEventValue.java index d539a84ec..1d427029e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaEventValue.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaEventValue.java @@ -1,46 +1,43 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Supplementary parameter for media events. - */ -public class MediaEventValue { - /** - * Callback parameter specified in the Value field of the MediaCard that - * originated this event. - */ - @JsonProperty(value = "cardValue") - private Object cardValue; - - /** - * Get the cardValue value. - * - * @return the cardValue value - */ - public Object cardValue() { - return this.cardValue; - } - - /** - * Set the cardValue value. - * - * @param cardValue the cardValue value to set - * @return the MediaEventValue object itself. - */ - public MediaEventValue withCardValue(Object cardValue) { - this.cardValue = cardValue; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Supplementary parameter for media events. + */ +public class MediaEventValue { + /** + * Callback parameter specified in the Value field of the MediaCard that + * originated this event. + */ + @JsonProperty(value = "cardValue") + private Object cardValue; + + public MediaEventValue(Object withCardValue) { + this.cardValue = withCardValue; + } + + /** + * Get the cardValue value. + * + * @return the cardValue value + */ + public Object getCardValue() { + return this.cardValue; + } + + /** + * Set the cardValue value. + * + * @param withCardValue the cardValue value to set + */ + public void setCardValue(Object withCardValue) { + this.cardValue = withCardValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaUrl.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaUrl.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaUrl.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaUrl.java index cbe993be2..2442498df 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MediaUrl.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaUrl.java @@ -1,72 +1,63 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Media URL. - */ -public class MediaUrl { - /** - * Url for the media. - */ - @JsonProperty(value = "url") - private String url; - - /** - * Optional profile hint to the client to differentiate multiple MediaUrl - * objects from each other. - */ - @JsonProperty(value = "profile") - private String profile; - - /** - * Get the url value. - * - * @return the url value - */ - public String url() { - return this.url; - } - - /** - * Set the url value. - * - * @param url the url value to set - * @return the MediaUrl object itself. - */ - public MediaUrl withUrl(String url) { - this.url = url; - return this; - } - - /** - * Get the profile value. - * - * @return the profile value - */ - public String profile() { - return this.profile; - } - - /** - * Set the profile value. - * - * @param profile the profile value to set - * @return the MediaUrl object itself. - */ - public MediaUrl withProfile(String profile) { - this.profile = profile; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Media URL. + */ +public class MediaUrl { + /** + * Url for the media. + */ + @JsonProperty(value = "url") + private String url; + + /** + * Optional profile hint to the client to differentiate multiple MediaUrl + * objects from each other. + */ + @JsonProperty(value = "profile") + private String profile; + + /** + * Get the url value. + * + * @return the url value + */ + public String getUrl() { + return this.url; + } + + /** + * Set the url value. + * + * @param withUrl the url value to set + */ + public void setUrl(String withUrl) { + this.url = withUrl; + } + + /** + * Get the profile value. + * + * @return the profile value + */ + public String getProfile() { + return this.profile; + } + + /** + * Set the profile value. + * + * @param withProfile the profile value to set + */ + public void setProfile(String withProfile) { + this.profile = withProfile; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Mention.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Mention.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Mention.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Mention.java index 32112fc83..7d30195da 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Mention.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Mention.java @@ -1,95 +1,81 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.microsoft.bot.schema.EntityImpl; - -/** - * Mention information (entity type: "mention"). - */ -public class Mention extends EntityImpl { - /** - * The mentioned user. - */ - @JsonProperty(value = "mentioned") - private ChannelAccount mentioned; - - /** - * Sub Text which represents the mention (can be null or empty). - */ - @JsonProperty(value = "text") - private String text; - - /** - * Type of this entity (RFC 3987 IRI). - */ - @JsonProperty(value = "type") - private String type; - - /** - * Get the mentioned value. - * - * @return the mentioned value - */ - public ChannelAccount mentioned() { - return this.mentioned; - } - - /** - * Set the mentioned value. - * - * @param mentioned the mentioned value to set - * @return the Mention object itself. - */ - public Mention withMentioned(ChannelAccount mentioned) { - this.mentioned = mentioned; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the Mention object itself. - */ - public Mention withText(String text) { - this.text = text; - return this; - } - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Mention object itself. - */ - public Mention withType(String type) { - this.type = type; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Mention information (entity type: "mention"). + */ +public class Mention implements EntitySerialization { + /** + * The mentioned user. + */ + @JsonProperty(value = "mentioned") + private ChannelAccount mentioned; + + /** + * Sub Text which represents the mention (can be null or empty). + */ + @JsonProperty(value = "text") + private String text; + + /** + * Type of this entity (RFC 3987 IRI). + */ + @JsonProperty(value = "type") + private String type; + + public Mention() { + this.type = "mention"; + } + + /** + * Get the mentioned value. + * + * @return the mentioned value + */ + public ChannelAccount getMentioned() { + return this.mentioned; + } + + /** + * Set the mentioned value. + * + * @param withMentioned the mentioned value to set + */ + public void setMentioned(ChannelAccount withMentioned) { + this.mentioned = withMentioned; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReaction.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReaction.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java index 31721c773..954acf1e4 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReaction.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java @@ -1,45 +1,38 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Message reaction object. - */ -public class MessageReaction { - /** - * Message reaction type. Possible values include: 'like', 'plusOne'. - */ - @JsonProperty(value = "type") - private MessageReactionTypes type; - - /** - * Get the type value. - * - * @return the type value - */ - public MessageReactionTypes type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the MessageReaction object itself. - */ - public MessageReaction withType(MessageReactionTypes type) { - this.type = type; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Message reaction object. + */ +public class MessageReaction { + /** + * Message reaction type. Possible values include: 'like', 'plusOne'. + */ + @JsonProperty(value = "type") + private MessageReactionTypes type; + + /** + * Get the type value. + * + * @return the type value + */ + public MessageReactionTypes getType() { + return this.type; + } + + /** + * Set the type value. + * + * @param withType the type value to set + */ + public void setType(MessageReactionTypes withType) { + this.type = withType; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReactionTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReactionTypes.java similarity index 68% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReactionTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReactionTypes.java index b3fb538dd..f53f0ceab 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageReactionTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReactionTypes.java @@ -1,55 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for MessageReactionTypes. - */ -public enum MessageReactionTypes { - /** Enum value like. */ - LIKE("like"), - - /** Enum value plusOne. */ - PLUS_ONE("plusOne"); - - /** The actual serialized value for a MessageReactionTypes instance. */ - private String value; - - MessageReactionTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a MessageReactionTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed MessageReactionTypes object, or null if unable to parse. - */ - @JsonCreator - public static MessageReactionTypes fromString(String value) { - MessageReactionTypes[] items = MessageReactionTypes.values(); - for (MessageReactionTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for MessageReactionTypes. + */ +public enum MessageReactionTypes { + /** + * Enum value like. + */ + LIKE("like"), + + /** + * Enum value plusOne. + */ + PLUS_ONE("plusOne"); + + /** + * The actual serialized value for a MessageReactionTypes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + MessageReactionTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a MessageReactionTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed MessageReactionTypes object, or null if unable to parse. + */ + @JsonCreator + public static MessageReactionTypes fromString(String value) { + MessageReactionTypes[] items = MessageReactionTypes.values(); + for (MessageReactionTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MicrosoftPayMethodData.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java similarity index 58% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MicrosoftPayMethodData.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java index 38d9088b4..ea121e3b7 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MicrosoftPayMethodData.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java @@ -1,98 +1,89 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * W3C Payment Method Data for Microsoft Pay. - */ -public class MicrosoftPayMethodData { - /** - * Microsoft Pay Merchant ID. - */ - @JsonProperty(value = "merchantId") - private String merchantId; - - /** - * Supported payment networks (e.g., "visa" and "mastercard"). - */ - @JsonProperty(value = "supportedNetworks") - private List supportedNetworks; - - /** - * Supported payment types (e.g., "credit"). - */ - @JsonProperty(value = "supportedTypes") - private List supportedTypes; - - /** - * Get the merchantId value. - * - * @return the merchantId value - */ - public String merchantId() { - return this.merchantId; - } - - /** - * Set the merchantId value. - * - * @param merchantId the merchantId value to set - * @return the MicrosoftPayMethodData object itself. - */ - public MicrosoftPayMethodData withMerchantId(String merchantId) { - this.merchantId = merchantId; - return this; - } - - /** - * Get the supportedNetworks value. - * - * @return the supportedNetworks value - */ - public List supportedNetworks() { - return this.supportedNetworks; - } - - /** - * Set the supportedNetworks value. - * - * @param supportedNetworks the supportedNetworks value to set - * @return the MicrosoftPayMethodData object itself. - */ - public MicrosoftPayMethodData withSupportedNetworks(List supportedNetworks) { - this.supportedNetworks = supportedNetworks; - return this; - } - - /** - * Get the supportedTypes value. - * - * @return the supportedTypes value - */ - public List supportedTypes() { - return this.supportedTypes; - } - - /** - * Set the supportedTypes value. - * - * @param supportedTypes the supportedTypes value to set - * @return the MicrosoftPayMethodData object itself. - */ - public MicrosoftPayMethodData withSupportedTypes(List supportedTypes) { - this.supportedTypes = supportedTypes; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * W3C Payment Method Data for Microsoft Pay. + */ +public class MicrosoftPayMethodData { + /** + * Microsoft Pay Merchant ID. + */ + @JsonProperty(value = "merchantId") + private String merchantId; + + /** + * Supported payment networks (e.g., "visa" and "mastercard"). + */ + @JsonProperty(value = "supportedNetworks") + private List supportedNetworks; + + /** + * Supported payment types (e.g., "credit"). + */ + @JsonProperty(value = "supportedTypes") + private List supportedTypes; + + /** + * Get the merchantId value. + * + * @return the merchantId value + */ + public String getMerchantId() { + return this.merchantId; + } + + /** + * Set the merchantId value. + * + * @param merchantId the merchantId value to set + * @return the MicrosoftPayMethodData object itself. + */ + public void setMerchantId(String withMerchantId) { + this.merchantId = withMerchantId; + } + + /** + * Get the supportedNetworks value. + * + * @return the supportedNetworks value + */ + public List getSupportedNetworks() { + return this.supportedNetworks; + } + + /** + * Set the supportedNetworks value. + * + * @param withSupportedNetworks the supportedNetworks value to set + */ + public void setSupportedNetworks(List withSupportedNetworks) { + this.supportedNetworks = withSupportedNetworks; + } + + /** + * Get the supportedTypes value. + * + * @return the supportedTypes value + */ + public List getSupportedTypes() { + return this.supportedTypes; + } + + /** + * Set the supportedTypes value. + * + * @param withSupportedTypes the supportedTypes value to set + */ + public void setSupportedTypes(List withSupportedTypes) { + this.supportedTypes = withSupportedTypes; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/OAuthCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/OAuthCard.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/OAuthCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/OAuthCard.java index 585f862a6..64c310cef 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/OAuthCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/OAuthCard.java @@ -1,98 +1,88 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A card representing a request to peform a sign in via OAuth. - */ -public class OAuthCard { - /** - * Text for signin request. - */ - @JsonProperty(value = "text") - private String text; - - /** - * The name of the registered connection. - */ - @JsonProperty(value = "connectionName") - private String connectionName; - - /** - * Action to use to perform signin. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the OAuthCard object itself. - */ - public OAuthCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the connectionName value. - * - * @return the connectionName value - */ - public String connectionName() { - return this.connectionName; - } - - /** - * Set the connectionName value. - * - * @param connectionName the connectionName value to set - * @return the OAuthCard object itself. - */ - public OAuthCard withConnectionName(String connectionName) { - this.connectionName = connectionName; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the OAuthCard object itself. - */ - public OAuthCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A card representing a request to peform a sign in via OAuth. + */ +public class OAuthCard { + /** + * Text for signin request. + */ + @JsonProperty(value = "text") + private String text; + + /** + * The name of the registered connection. + */ + @JsonProperty(value = "connectionName") + private String connectionName; + + /** + * Action to use to perform signin. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the connectionName value. + * + * @return the connectionName value + */ + public String getConnectionName() { + return this.connectionName; + } + + /** + * Set the connectionName value. + * + * @param withConnectionName the connectionName value to set + */ + public void setConnectionName(String withConnectionName) { + this.connectionName = withConnectionName; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PagedMembersResult.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PagedMembersResult.java similarity index 52% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PagedMembersResult.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PagedMembersResult.java index 61a1aa6e0..250ea7af7 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PagedMembersResult.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PagedMembersResult.java @@ -1,66 +1,58 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Page of members - */ -public class PagedMembersResult { - - @JsonProperty(value = "continuationToken") - private String continuationToken; - - /** - * List of members in this conversation. - */ - @JsonProperty(value = "members") - private List members; - - /** - * Gets paging token - */ - public String continuationToken(){ - return this.continuationToken; - } - - /** - * Sets paging token - * - * @return the PagedMembersResult object itself. - */ - public PagedMembersResult withContinuationToken(String continuationToken){ - this.continuationToken = continuationToken; - return this; - } - - /** - * Gets the Channel Accounts. - * - * @return the members value - */ - public List members() { - return this.members; - } - - /** - * Sets the Channel Accounts. - * - * @param members the members value to set - * @return the PagedMembersResult object itself. - */ - public PagedMembersResult withMembers(List members) { - this.members = members; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Page of members + */ +public class PagedMembersResult { + + @JsonProperty(value = "continuationToken") + private String continuationToken; + + /** + * List of members in this conversation. + */ + @JsonProperty(value = "members") + private List members; + + /** + * Gets paging token + */ + public String getContinuationToken() { + return this.continuationToken; + } + + /**s + * Sets paging token + */ + public void setContinuationToken(String withContinuationToken) { + this.continuationToken = withContinuationToken; + } + + /** + * Gets the Channel Accounts. + * + * @return the members value + */ + public List getMembers() { + return this.members; + } + + /** + * Sets the Channel Accounts. + * + * @param withMembers the members value to set + */ + public void setMembers(List withMembers) { + this.members = withMembers; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentAddress.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentAddress.java similarity index 60% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentAddress.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentAddress.java index 0e7b24f08..2a087c650 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentAddress.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentAddress.java @@ -1,314 +1,291 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Address within a Payment Request. - */ -public class PaymentAddress { - /** - * This is the CLDR (Common Locale Data Repository) region code. For - * example, US, GB, CN, or JP. - */ - @JsonProperty(value = "country") - private String country; - - /** - * This is the most specific part of the address. It can include, for - * example, a street name, a house number, apartment number, a rural - * delivery route, descriptive instructions, or a post office box number. - */ - @JsonProperty(value = "addressLine") - private List addressLine; - - /** - * This is the top level administrative subdivision of the country. For - * example, this can be a state, a province, an oblast, or a prefecture. - */ - @JsonProperty(value = "region") - private String region; - - /** - * This is the city/town portion of the address. - */ - @JsonProperty(value = "city") - private String city; - - /** - * This is the dependent locality or sublocality within a city. For - * example, used for neighborhoods, boroughs, districts, or UK dependent - * localities. - */ - @JsonProperty(value = "dependentLocality") - private String dependentLocality; - - /** - * This is the postal code or ZIP code, also known as PIN code in India. - */ - @JsonProperty(value = "postalCode") - private String postalCode; - - /** - * This is the sorting code as used in, for example, France. - */ - @JsonProperty(value = "sortingCode") - private String sortingCode; - - /** - * This is the BCP-47 language code for the address. It's used to determine - * the field separators and the order of fields when formatting the address - * for display. - */ - @JsonProperty(value = "languageCode") - private String languageCode; - - /** - * This is the organization, firm, company, or institution at this address. - */ - @JsonProperty(value = "organization") - private String organization; - - /** - * This is the name of the recipient or contact person. - */ - @JsonProperty(value = "recipient") - private String recipient; - - /** - * This is the phone number of the recipient or contact person. - */ - @JsonProperty(value = "phone") - private String phone; - - /** - * Get the country value. - * - * @return the country value - */ - public String country() { - return this.country; - } - - /** - * Set the country value. - * - * @param country the country value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withCountry(String country) { - this.country = country; - return this; - } - - /** - * Get the addressLine value. - * - * @return the addressLine value - */ - public List addressLine() { - return this.addressLine; - } - - /** - * Set the addressLine value. - * - * @param addressLine the addressLine value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withAddressLine(List addressLine) { - this.addressLine = addressLine; - return this; - } - - /** - * Get the region value. - * - * @return the region value - */ - public String region() { - return this.region; - } - - /** - * Set the region value. - * - * @param region the region value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withRegion(String region) { - this.region = region; - return this; - } - - /** - * Get the city value. - * - * @return the city value - */ - public String city() { - return this.city; - } - - /** - * Set the city value. - * - * @param city the city value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withCity(String city) { - this.city = city; - return this; - } - - /** - * Get the dependentLocality value. - * - * @return the dependentLocality value - */ - public String dependentLocality() { - return this.dependentLocality; - } - - /** - * Set the dependentLocality value. - * - * @param dependentLocality the dependentLocality value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withDependentLocality(String dependentLocality) { - this.dependentLocality = dependentLocality; - return this; - } - - /** - * Get the postalCode value. - * - * @return the postalCode value - */ - public String postalCode() { - return this.postalCode; - } - - /** - * Set the postalCode value. - * - * @param postalCode the postalCode value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withPostalCode(String postalCode) { - this.postalCode = postalCode; - return this; - } - - /** - * Get the sortingCode value. - * - * @return the sortingCode value - */ - public String sortingCode() { - return this.sortingCode; - } - - /** - * Set the sortingCode value. - * - * @param sortingCode the sortingCode value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withSortingCode(String sortingCode) { - this.sortingCode = sortingCode; - return this; - } - - /** - * Get the languageCode value. - * - * @return the languageCode value - */ - public String languageCode() { - return this.languageCode; - } - - /** - * Set the languageCode value. - * - * @param languageCode the languageCode value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withLanguageCode(String languageCode) { - this.languageCode = languageCode; - return this; - } - - /** - * Get the organization value. - * - * @return the organization value - */ - public String organization() { - return this.organization; - } - - /** - * Set the organization value. - * - * @param organization the organization value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withOrganization(String organization) { - this.organization = organization; - return this; - } - - /** - * Get the recipient value. - * - * @return the recipient value - */ - public String recipient() { - return this.recipient; - } - - /** - * Set the recipient value. - * - * @param recipient the recipient value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withRecipient(String recipient) { - this.recipient = recipient; - return this; - } - - /** - * Get the phone value. - * - * @return the phone value - */ - public String phone() { - return this.phone; - } - - /** - * Set the phone value. - * - * @param phone the phone value to set - * @return the PaymentAddress object itself. - */ - public PaymentAddress withPhone(String phone) { - this.phone = phone; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Address within a Payment Request. + */ +public class PaymentAddress { + /** + * This is the CLDR (Common Locale Data Repository) region code. For + * example, US, GB, CN, or JP. + */ + @JsonProperty(value = "country") + private String country; + + /** + * This is the most specific part of the address. It can include, for + * example, a street name, a house number, apartment number, a rural + * delivery route, descriptive instructions, or a post office box number. + */ + @JsonProperty(value = "addressLine") + private List addressLine; + + /** + * This is the top level administrative subdivision of the country. For + * example, this can be a state, a province, an oblast, or a prefecture. + */ + @JsonProperty(value = "region") + private String region; + + /** + * This is the city/town portion of the address. + */ + @JsonProperty(value = "city") + private String city; + + /** + * This is the dependent locality or sublocality within a city. For + * example, used for neighborhoods, boroughs, districts, or UK dependent + * localities. + */ + @JsonProperty(value = "dependentLocality") + private String dependentLocality; + + /** + * This is the postal code or ZIP code, also known as PIN code in India. + */ + @JsonProperty(value = "postalCode") + private String postalCode; + + /** + * This is the sorting code as used in, for example, France. + */ + @JsonProperty(value = "sortingCode") + private String sortingCode; + + /** + * This is the BCP-47 language code for the address. It's used to determine + * the field separators and the order of fields when formatting the address + * for display. + */ + @JsonProperty(value = "languageCode") + private String languageCode; + + /** + * This is the organization, firm, company, or institution at this address. + */ + @JsonProperty(value = "organization") + private String organization; + + /** + * This is the name of the recipient or contact person. + */ + @JsonProperty(value = "recipient") + private String recipient; + + /** + * This is the phone number of the recipient or contact person. + */ + @JsonProperty(value = "phone") + private String phone; + + /** + * Get the country value. + * + * @return the country value + */ + public String getCountry() { + return this.country; + } + + /** + * Set the country value. + * + * @param withCountry the country value to set + */ + public void setCountry(String withCountry) { + this.country = withCountry; + } + + /** + * Get the addressLine value. + * + * @return the addressLine value + */ + public List getAddressLine() { + return this.addressLine; + } + + /** + * Set the addressLine value. + * + * @param withAddressLine the addressLine value to set + */ + public void setAddressLine(List withAddressLine) { + this.addressLine = withAddressLine; + } + + /** + * Get the region value. + * + * @return the region value + */ + public String getRegion() { + return this.region; + } + + /** + * Set the region value. + * + * @param withRegion the region value to set + */ + public void setRegion(String withRegion) { + this.region = withRegion; + } + + /** + * Get the city value. + * + * @return the city value + */ + public String getCity() { + return this.city; + } + + /** + * Set the city value. + * + * @param withCity the city value to set + */ + public void setCity(String withCity) { + this.city = withCity; + } + + /** + * Get the dependentLocality value. + * + * @return the dependentLocality value + */ + public String getDependentLocality() { + return this.dependentLocality; + } + + /** + * Set the dependentLocality value. + * + * @param withDependentLocality the dependentLocality value to set + * @return the PaymentAddress object itself. + */ + public void setDependentLocality(String withDependentLocality) { + this.dependentLocality = withDependentLocality; + } + + /** + * Get the postalCode value. + * + * @return the postalCode value + */ + public String postalCode() { + return this.postalCode; + } + + /** + * Set the postalCode value. + * + * @param withPostalCode the postalCode value to set + * @return the PaymentAddress object itself. + */ + public void setPostalCode(String withPostalCode) { + this.postalCode = withPostalCode; + } + + /** + * Get the sortingCode value. + * + * @return the sortingCode value + */ + public String getSortingCode() { + return this.sortingCode; + } + + /** + * Set the sortingCode value. + * + * @param withSortingCode the sortingCode value to set + */ + public void setSortingCode(String withSortingCode) { + this.sortingCode = withSortingCode; + } + + /** + * Get the languageCode value. + * + * @return the languageCode value + */ + public String getLanguageCode() { + return this.languageCode; + } + + /** + * Set the languageCode value. + * + * @param withLanguageCode the languageCode value to set + * @return the PaymentAddress object itself. + */ + public void setLanguageCode(String withLanguageCode) { + this.languageCode = withLanguageCode; + } + + /** + * Get the organization value. + * + * @return the organization value + */ + public String getOrganization() { + return this.organization; + } + + /** + * Set the organization value. + * + * @param withOrganization the organization value to set + */ + public void setOrganization(String withOrganization) { + this.organization = withOrganization; + } + + /** + * Get the recipient value. + * + * @return the recipient value + */ + public String getRecipient() { + return this.recipient; + } + + /** + * Set the recipient value. + * + * @param withRecipient the recipient value to set + */ + public void setRecipient(String withRecipient) { + this.recipient = withRecipient; + } + + /** + * Get the phone value. + * + * @return the phone value + */ + public String getPhone() { + return this.phone; + } + + /** + * Set the phone value. + * + * @param withPhone the phone value to set + */ + public void setPhone(String withPhone) { + this.phone = withPhone; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentCurrencyAmount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentCurrencyAmount.java similarity index 52% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentCurrencyAmount.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentCurrencyAmount.java index d210b4155..acc93107b 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentCurrencyAmount.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentCurrencyAmount.java @@ -1,97 +1,86 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Supplies monetary amounts. - */ -public class PaymentCurrencyAmount { - /** - * A currency identifier. - */ - @JsonProperty(value = "currency") - private String currency; - - /** - * Decimal monetary value. - */ - @JsonProperty(value = "value") - private String value; - - /** - * Currency system. - */ - @JsonProperty(value = "currencySystem") - private String currencySystem; - - /** - * Get the currency value. - * - * @return the currency value - */ - public String currency() { - return this.currency; - } - - /** - * Set the currency value. - * - * @param currency the currency value to set - * @return the PaymentCurrencyAmount object itself. - */ - public PaymentCurrencyAmount withCurrency(String currency) { - this.currency = currency; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public String value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the PaymentCurrencyAmount object itself. - */ - public PaymentCurrencyAmount withValue(String value) { - this.value = value; - return this; - } - - /** - * Get the currencySystem value. - * - * @return the currencySystem value - */ - public String currencySystem() { - return this.currencySystem; - } - - /** - * Set the currencySystem value. - * - * @param currencySystem the currencySystem value to set - * @return the PaymentCurrencyAmount object itself. - */ - public PaymentCurrencyAmount withCurrencySystem(String currencySystem) { - this.currencySystem = currencySystem; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Supplies monetary amounts. + */ +public class PaymentCurrencyAmount { + /** + * A currency identifier. + */ + @JsonProperty(value = "currency") + private String currency; + + /** + * Decimal monetary value. + */ + @JsonProperty(value = "value") + private String value; + + /** + * Currency system. + */ + @JsonProperty(value = "currencySystem") + private String currencySystem; + + /** + * Get the currency value. + * + * @return the currency value + */ + public String getCurrency() { + return this.currency; + } + + /** + * Set the currency value. + * + * @param withCurrency the currency value to set + */ + public void setCurrency(String withCurrency) { + this.currency = withCurrency; + } + + /** + * Get the value value. + * + * @return the value value + */ + public String getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(String withValue) { + this.value = withValue; + } + + /** + * Get the currencySystem value. + * + * @return the currencySystem value + */ + public String getCurrencySystem() { + return this.currencySystem; + } + + /** + * Set the currencySystem value. + * + * @param withCurrencySystem the currencySystem value to set + */ + public void setCurrencySystem(String withCurrencySystem) { + this.currencySystem = withCurrencySystem; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetails.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetails.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetails.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetails.java index 07561f55c..ace1d575e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetails.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetails.java @@ -1,152 +1,138 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Provides information about the requested transaction. - */ -public class PaymentDetails { - /** - * Contains the total amount of the payment request. - */ - @JsonProperty(value = "total") - private PaymentItem total; - - /** - * Contains line items for the payment request that the user agent may - * display. - */ - @JsonProperty(value = "displayItems") - private List displayItems; - - /** - * A sequence containing the different shipping options for the user to - * choose from. - */ - @JsonProperty(value = "shippingOptions") - private List shippingOptions; - - /** - * Contains modifiers for particular payment method identifiers. - */ - @JsonProperty(value = "modifiers") - private List modifiers; - - /** - * Error description. - */ - @JsonProperty(value = "error") - private String error; - - /** - * Get the total value. - * - * @return the total value - */ - public PaymentItem total() { - return this.total; - } - - /** - * Set the total value. - * - * @param total the total value to set - * @return the PaymentDetails object itself. - */ - public PaymentDetails withTotal(PaymentItem total) { - this.total = total; - return this; - } - - /** - * Get the displayItems value. - * - * @return the displayItems value - */ - public List displayItems() { - return this.displayItems; - } - - /** - * Set the displayItems value. - * - * @param displayItems the displayItems value to set - * @return the PaymentDetails object itself. - */ - public PaymentDetails withDisplayItems(List displayItems) { - this.displayItems = displayItems; - return this; - } - - /** - * Get the shippingOptions value. - * - * @return the shippingOptions value - */ - public List shippingOptions() { - return this.shippingOptions; - } - - /** - * Set the shippingOptions value. - * - * @param shippingOptions the shippingOptions value to set - * @return the PaymentDetails object itself. - */ - public PaymentDetails withShippingOptions(List shippingOptions) { - this.shippingOptions = shippingOptions; - return this; - } - - /** - * Get the modifiers value. - * - * @return the modifiers value - */ - public List modifiers() { - return this.modifiers; - } - - /** - * Set the modifiers value. - * - * @param modifiers the modifiers value to set - * @return the PaymentDetails object itself. - */ - public PaymentDetails withModifiers(List modifiers) { - this.modifiers = modifiers; - return this; - } - - /** - * Get the error value. - * - * @return the error value - */ - public String error() { - return this.error; - } - - /** - * Set the error value. - * - * @param error the error value to set - * @return the PaymentDetails object itself. - */ - public PaymentDetails withError(String error) { - this.error = error; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Provides information about the requested transaction. + */ +public class PaymentDetails { + /** + * Contains the total amount of the payment request. + */ + @JsonProperty(value = "total") + private PaymentItem total; + + /** + * Contains line items for the payment request that the user agent may + * display. + */ + @JsonProperty(value = "displayItems") + private List displayItems; + + /** + * A sequence containing the different shipping options for the user to + * choose from. + */ + @JsonProperty(value = "shippingOptions") + private List shippingOptions; + + /** + * Contains modifiers for particular payment method identifiers. + */ + @JsonProperty(value = "modifiers") + private List modifiers; + + /** + * Error description. + */ + @JsonProperty(value = "error") + private String error; + + /** + * Get the total value. + * + * @return the total value + */ + public PaymentItem getTotal() { + return this.total; + } + + /** + * Set the total value. + * + * @param withTotal the total value to set + */ + public void setTotal(PaymentItem withTotal) { + this.total = withTotal; + } + + /** + * Get the displayItems value. + * + * @return the displayItems value + */ + public List getDisplayItems() { + return this.displayItems; + } + + /** + * Set the displayItems value. + * + * @param withDisplayItems the displayItems value to set + */ + public void setDisplayItems(List withDisplayItems) { + this.displayItems = withDisplayItems; + } + + /** + * Get the shippingOptions value. + * + * @return the shippingOptions value + */ + public List getShippingOptions() { + return this.shippingOptions; + } + + /** + * Set the shippingOptions value. + * + * @param withShippingOptions the shippingOptions value to set + */ + public void setShippingOptions(List withShippingOptions) { + this.shippingOptions = withShippingOptions; + } + + /** + * Get the modifiers value. + * + * @return the modifiers value + */ + public List getModifiers() { + return this.modifiers; + } + + /** + * Set the modifiers value. + * + * @param withModifiers the modifiers value to set + */ + public void setModifiers(List withModifiers) { + this.modifiers = withModifiers; + } + + /** + * Get the error value. + * + * @return the error value + */ + public String getError() { + return this.error; + } + + /** + * Set the error value. + * + * @param withError the error value to set + */ + public void setError(String withError) { + this.error = withError; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetailsModifier.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetailsModifier.java similarity index 58% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetailsModifier.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetailsModifier.java index 12b3e36c4..b5ddd1f94 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentDetailsModifier.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentDetailsModifier.java @@ -1,129 +1,117 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Provides details that modify the PaymentDetails based on payment method - * identifier. - */ -public class PaymentDetailsModifier { - /** - * Contains a sequence of payment method identifiers. - */ - @JsonProperty(value = "supportedMethods") - private List supportedMethods; - - /** - * This value overrides the total field in the PaymentDetails dictionary - * for the payment method identifiers in the supportedMethods field. - */ - @JsonProperty(value = "total") - private PaymentItem total; - - /** - * Provides additional display items that are appended to the displayItems - * field in the PaymentDetails dictionary for the payment method - * identifiers in the supportedMethods field. - */ - @JsonProperty(value = "additionalDisplayItems") - private List additionalDisplayItems; - - /** - * A JSON-serializable object that provides optional information that might - * be needed by the supported payment methods. - */ - @JsonProperty(value = "data") - private Object data; - - /** - * Get the supportedMethods value. - * - * @return the supportedMethods value - */ - public List supportedMethods() { - return this.supportedMethods; - } - - /** - * Set the supportedMethods value. - * - * @param supportedMethods the supportedMethods value to set - * @return the PaymentDetailsModifier object itself. - */ - public PaymentDetailsModifier withSupportedMethods(List supportedMethods) { - this.supportedMethods = supportedMethods; - return this; - } - - /** - * Get the total value. - * - * @return the total value - */ - public PaymentItem total() { - return this.total; - } - - /** - * Set the total value. - * - * @param total the total value to set - * @return the PaymentDetailsModifier object itself. - */ - public PaymentDetailsModifier withTotal(PaymentItem total) { - this.total = total; - return this; - } - - /** - * Get the additionalDisplayItems value. - * - * @return the additionalDisplayItems value - */ - public List additionalDisplayItems() { - return this.additionalDisplayItems; - } - - /** - * Set the additionalDisplayItems value. - * - * @param additionalDisplayItems the additionalDisplayItems value to set - * @return the PaymentDetailsModifier object itself. - */ - public PaymentDetailsModifier withAdditionalDisplayItems(List additionalDisplayItems) { - this.additionalDisplayItems = additionalDisplayItems; - return this; - } - - /** - * Get the data value. - * - * @return the data value - */ - public Object data() { - return this.data; - } - - /** - * Set the data value. - * - * @param data the data value to set - * @return the PaymentDetailsModifier object itself. - */ - public PaymentDetailsModifier withData(Object data) { - this.data = data; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Provides details that modify the PaymentDetails based on payment method + * identifier. + */ +public class PaymentDetailsModifier { + /** + * Contains a sequence of payment method identifiers. + */ + @JsonProperty(value = "supportedMethods") + private List supportedMethods; + + /** + * This value overrides the total field in the PaymentDetails dictionary + * for the payment method identifiers in the supportedMethods field. + */ + @JsonProperty(value = "total") + private PaymentItem total; + + /** + * Provides additional display items that are appended to the displayItems + * field in the PaymentDetails dictionary for the payment method + * identifiers in the supportedMethods field. + */ + @JsonProperty(value = "additionalDisplayItems") + private List additionalDisplayItems; + + /** + * A JSON-serializable object that provides optional information that might + * be needed by the supported payment methods. + */ + @JsonProperty(value = "data") + private Object data; + + /** + * Get the supportedMethods value. + * + * @return the supportedMethods value + */ + public List getSupportedMethods() { + return this.supportedMethods; + } + + /** + * Set the supportedMethods value. + * + * @param withSupportedMethods the supportedMethods value to set + */ + public void setSupportedMethods(List withSupportedMethods) { + this.supportedMethods = withSupportedMethods; + } + + /** + * Get the total value. + * + * @return the total value + */ + public PaymentItem getTotal() { + return this.total; + } + + /** + * Set the total value. + * + * @param withTotal the total value to set + */ + public void setTotal(PaymentItem withTotal) { + this.total = withTotal; + } + + /** + * Get the additionalDisplayItems value. + * + * @return the additionalDisplayItems value + */ + public List getAdditionalDisplayItems() { + return this.additionalDisplayItems; + } + + /** + * Set the additionalDisplayItems value. + * + * @param withAdditionalDisplayItems the additionalDisplayItems value to set + */ + public void setAdditionalDisplayItems(List withAdditionalDisplayItems) { + this.additionalDisplayItems = withAdditionalDisplayItems; + } + + /** + * Get the data value. + * + * @return the data value + */ + public Object getData() { + return this.data; + } + + /** + * Set the data value. + * + * @param withData the data value to set + */ + public void setData(Object withData) { + this.data = withData; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentItem.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentItem.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentItem.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentItem.java index 9d707242c..f4768aa24 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentItem.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentItem.java @@ -1,97 +1,86 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Indicates what the payment request is for and the value asked for. - */ -public class PaymentItem { - /** - * Human-readable description of the item. - */ - @JsonProperty(value = "label") - private String label; - - /** - * Monetary amount for the item. - */ - @JsonProperty(value = "amount") - private PaymentCurrencyAmount amount; - - /** - * When set to true this flag means that the amount field is not final. - */ - @JsonProperty(value = "pending") - private Boolean pending; - - /** - * Get the label value. - * - * @return the label value - */ - public String label() { - return this.label; - } - - /** - * Set the label value. - * - * @param label the label value to set - * @return the PaymentItem object itself. - */ - public PaymentItem withLabel(String label) { - this.label = label; - return this; - } - - /** - * Get the amount value. - * - * @return the amount value - */ - public PaymentCurrencyAmount amount() { - return this.amount; - } - - /** - * Set the amount value. - * - * @param amount the amount value to set - * @return the PaymentItem object itself. - */ - public PaymentItem withAmount(PaymentCurrencyAmount amount) { - this.amount = amount; - return this; - } - - /** - * Get the pending value. - * - * @return the pending value - */ - public Boolean pending() { - return this.pending; - } - - /** - * Set the pending value. - * - * @param pending the pending value to set - * @return the PaymentItem object itself. - */ - public PaymentItem withPending(Boolean pending) { - this.pending = pending; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Indicates what the payment request is for and the value asked for. + */ +public class PaymentItem { + /** + * Human-readable description of the item. + */ + @JsonProperty(value = "label") + private String label; + + /** + * Monetary amount for the item. + */ + @JsonProperty(value = "amount") + private PaymentCurrencyAmount amount; + + /** + * When set to true this flag means that the amount field is not final. + */ + @JsonProperty(value = "pending") + private boolean pending; + + /** + * Get the label value. + * + * @return the label value + */ + public String getLabel() { + return this.label; + } + + /** + * Set the label value. + * + * @param withLabel the label value to set + */ + public void setLabel(String withLabel) { + this.label = withLabel; + } + + /** + * Get the amount value. + * + * @return the amount value + */ + public PaymentCurrencyAmount getAmount() { + return this.amount; + } + + /** + * Set the amount value. + * + * @param withAmount the amount value to set + */ + public void setAmount(PaymentCurrencyAmount withAmount) { + this.amount = withAmount; + } + + /** + * Get the pending value. + * + * @return the pending value + */ + public boolean getPending() { + return this.pending; + } + + /** + * Set the pending value. + * + * @param withPending the pending value to set + */ + public void setPending(boolean withPending) { + this.pending = withPending; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentMethodData.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentMethodData.java similarity index 60% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentMethodData.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentMethodData.java index 94cd64bfe..b63df41cf 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentMethodData.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentMethodData.java @@ -1,75 +1,67 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Indicates a set of supported payment methods and any associated payment - * method specific data for those methods. - */ -public class PaymentMethodData { - /** - * Required sequence of strings containing payment method identifiers for - * payment methods that the merchant web site accepts. - */ - @JsonProperty(value = "supportedMethods") - private List supportedMethods; - - /** - * A JSON-serializable object that provides optional information that might - * be needed by the supported payment methods. - */ - @JsonProperty(value = "data") - private Object data; - - /** - * Get the supportedMethods value. - * - * @return the supportedMethods value - */ - public List supportedMethods() { - return this.supportedMethods; - } - - /** - * Set the supportedMethods value. - * - * @param supportedMethods the supportedMethods value to set - * @return the PaymentMethodData object itself. - */ - public PaymentMethodData withSupportedMethods(List supportedMethods) { - this.supportedMethods = supportedMethods; - return this; - } - - /** - * Get the data value. - * - * @return the data value - */ - public Object data() { - return this.data; - } - - /** - * Set the data value. - * - * @param data the data value to set - * @return the PaymentMethodData object itself. - */ - public PaymentMethodData withData(Object data) { - this.data = data; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Indicates a set of supported payment methods and any associated payment + * method specific data for those methods. + */ +public class PaymentMethodData { + /** + * Required sequence of strings containing payment method identifiers for + * payment methods that the merchant web site accepts. + */ + @JsonProperty(value = "supportedMethods") + private List supportedMethods; + + /** + * A JSON-serializable object that provides optional information that might + * be needed by the supported payment methods. + */ + @JsonProperty(value = "data") + private Object data; + + /** + * Get the supportedMethods value. + * + * @return the supportedMethods value + */ + public List getSupportedMethods() { + return this.supportedMethods; + } + + /** + * Set the supportedMethods value. + * + * @param withSupportedMethods the supportedMethods value to set + */ + public void setSupportedMethods(List withSupportedMethods) { + this.supportedMethods = withSupportedMethods; + } + + /** + * Get the data value. + * + * @return the data value + */ + public Object getData() { + return this.data; + } + + /** + * Set the data value. + * + * @param withData the data value to set + */ + public void setData(Object withData) { + this.data = withData; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentOptions.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentOptions.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentOptions.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentOptions.java index 86ac8fd6f..e06db9619 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentOptions.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentOptions.java @@ -1,155 +1,140 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Provides information about the options desired for the payment request. - */ -public class PaymentOptions { - /** - * Indicates whether the user agent should collect and return the payer's - * name as part of the payment request. - */ - @JsonProperty(value = "requestPayerName") - private Boolean requestPayerName; - - /** - * Indicates whether the user agent should collect and return the payer's - * email address as part of the payment request. - */ - @JsonProperty(value = "requestPayerEmail") - private Boolean requestPayerEmail; - - /** - * Indicates whether the user agent should collect and return the payer's - * phone number as part of the payment request. - */ - @JsonProperty(value = "requestPayerPhone") - private Boolean requestPayerPhone; - - /** - * Indicates whether the user agent should collect and return a shipping - * address as part of the payment request. - */ - @JsonProperty(value = "requestShipping") - private Boolean requestShipping; - - /** - * If requestShipping is set to true, then the shippingType field may be - * used to influence the way the user agent presents the user interface for - * gathering the shipping address. - */ - @JsonProperty(value = "shippingType") - private String shippingType; - - /** - * Get the requestPayerName value. - * - * @return the requestPayerName value - */ - public Boolean requestPayerName() { - return this.requestPayerName; - } - - /** - * Set the requestPayerName value. - * - * @param requestPayerName the requestPayerName value to set - * @return the PaymentOptions object itself. - */ - public PaymentOptions withRequestPayerName(Boolean requestPayerName) { - this.requestPayerName = requestPayerName; - return this; - } - - /** - * Get the requestPayerEmail value. - * - * @return the requestPayerEmail value - */ - public Boolean requestPayerEmail() { - return this.requestPayerEmail; - } - - /** - * Set the requestPayerEmail value. - * - * @param requestPayerEmail the requestPayerEmail value to set - * @return the PaymentOptions object itself. - */ - public PaymentOptions withRequestPayerEmail(Boolean requestPayerEmail) { - this.requestPayerEmail = requestPayerEmail; - return this; - } - - /** - * Get the requestPayerPhone value. - * - * @return the requestPayerPhone value - */ - public Boolean requestPayerPhone() { - return this.requestPayerPhone; - } - - /** - * Set the requestPayerPhone value. - * - * @param requestPayerPhone the requestPayerPhone value to set - * @return the PaymentOptions object itself. - */ - public PaymentOptions withRequestPayerPhone(Boolean requestPayerPhone) { - this.requestPayerPhone = requestPayerPhone; - return this; - } - - /** - * Get the requestShipping value. - * - * @return the requestShipping value - */ - public Boolean requestShipping() { - return this.requestShipping; - } - - /** - * Set the requestShipping value. - * - * @param requestShipping the requestShipping value to set - * @return the PaymentOptions object itself. - */ - public PaymentOptions withRequestShipping(Boolean requestShipping) { - this.requestShipping = requestShipping; - return this; - } - - /** - * Get the shippingType value. - * - * @return the shippingType value - */ - public String shippingType() { - return this.shippingType; - } - - /** - * Set the shippingType value. - * - * @param shippingType the shippingType value to set - * @return the PaymentOptions object itself. - */ - public PaymentOptions withShippingType(String shippingType) { - this.shippingType = shippingType; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Provides information about the options desired for the payment request. + */ +public class PaymentOptions { + /** + * Indicates whether the user agent should collect and return the payer's + * name as part of the payment request. + */ + @JsonProperty(value = "requestPayerName") + private boolean requestPayerName; + + /** + * Indicates whether the user agent should collect and return the payer's + * email address as part of the payment request. + */ + @JsonProperty(value = "requestPayerEmail") + private boolean requestPayerEmail; + + /** + * Indicates whether the user agent should collect and return the payer's + * phone number as part of the payment request. + */ + @JsonProperty(value = "requestPayerPhone") + private boolean requestPayerPhone; + + /** + * Indicates whether the user agent should collect and return a shipping + * address as part of the payment request. + */ + @JsonProperty(value = "requestShipping") + private boolean requestShipping; + + /** + * If requestShipping is set to true, then the shippingType field may be + * used to influence the way the user agent presents the user interface for + * gathering the shipping address. + */ + @JsonProperty(value = "shippingType") + private String shippingType; + + /** + * Get the requestPayerName value. + * + * @return the requestPayerName value + */ + public boolean getRequestPayerName() { + return this.requestPayerName; + } + + /** + * Set the requestPayerName value. + * + * @param withRequestPayerName the requestPayerName value to set + */ + public void setRequestPayerName(boolean withRequestPayerName) { + this.requestPayerName = withRequestPayerName; + } + + /** + * Get the requestPayerEmail value. + * + * @return the requestPayerEmail value + */ + public boolean getRequestPayerEmail() { + return this.requestPayerEmail; + } + + /** + * Set the requestPayerEmail value. + * + * @param withRequestPayerEmail the requestPayerEmail value to set + */ + public void setRequestPayerEmail(boolean withRequestPayerEmail) { + this.requestPayerEmail = withRequestPayerEmail; + } + + /** + * Get the requestPayerPhone value. + * + * @return the requestPayerPhone value + */ + public boolean getRequestPayerPhone() { + return this.requestPayerPhone; + } + + /** + * Set the requestPayerPhone value. + * + * @param withRequestPayerPhone the requestPayerPhone value to set + */ + public void setRequestPayerPhone(boolean withRequestPayerPhone) { + this.requestPayerPhone = withRequestPayerPhone; + } + + /** + * Get the requestShipping value. + * + * @return the requestShipping value + */ + public boolean getRequestShipping() { + return this.requestShipping; + } + + /** + * Set the requestShipping value. + * + * @param withRequestShipping the requestShipping value to set + */ + public void setRequestShipping(boolean withRequestShipping) { + this.requestShipping = withRequestShipping; + } + + /** + * Get the shippingType value. + * + * @return the shippingType value + */ + public String getShippingType() { + return this.shippingType; + } + + /** + * Set the shippingType value. + * + * @param withShippingType the shippingType value to set + */ + public void setShippingType(String withShippingType) { + this.shippingType = withShippingType; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequest.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequest.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequest.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequest.java index 07b22384d..cfdc6c32b 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequest.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequest.java @@ -1,150 +1,136 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A request to make a payment. - */ -public class PaymentRequest { - /** - * ID of this payment request. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Allowed payment methods for this request. - */ - @JsonProperty(value = "methodData") - private List methodData; - - /** - * Details for this request. - */ - @JsonProperty(value = "details") - private PaymentDetails details; - - /** - * Provides information about the options desired for the payment request. - */ - @JsonProperty(value = "options") - private PaymentOptions options; - - /** - * Expiration for this request, in ISO 8601 duration format (e.g., 'P1D'). - */ - @JsonProperty(value = "expires") - private String expires; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the PaymentRequest object itself. - */ - public PaymentRequest withId(String id) { - this.id = id; - return this; - } - - /** - * Get the methodData value. - * - * @return the methodData value - */ - public List methodData() { - return this.methodData; - } - - /** - * Set the methodData value. - * - * @param methodData the methodData value to set - * @return the PaymentRequest object itself. - */ - public PaymentRequest withMethodData(List methodData) { - this.methodData = methodData; - return this; - } - - /** - * Get the details value. - * - * @return the details value - */ - public PaymentDetails details() { - return this.details; - } - - /** - * Set the details value. - * - * @param details the details value to set - * @return the PaymentRequest object itself. - */ - public PaymentRequest withDetails(PaymentDetails details) { - this.details = details; - return this; - } - - /** - * Get the options value. - * - * @return the options value - */ - public PaymentOptions options() { - return this.options; - } - - /** - * Set the options value. - * - * @param options the options value to set - * @return the PaymentRequest object itself. - */ - public PaymentRequest withOptions(PaymentOptions options) { - this.options = options; - return this; - } - - /** - * Get the expires value. - * - * @return the expires value - */ - public String expires() { - return this.expires; - } - - /** - * Set the expires value. - * - * @param expires the expires value to set - * @return the PaymentRequest object itself. - */ - public PaymentRequest withExpires(String expires) { - this.expires = expires; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A request to make a payment. + */ +public class PaymentRequest { + /** + * ID of this payment request. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Allowed payment methods for this request. + */ + @JsonProperty(value = "methodData") + private List methodData; + + /** + * Details for this request. + */ + @JsonProperty(value = "details") + private PaymentDetails details; + + /** + * Provides information about the options desired for the payment request. + */ + @JsonProperty(value = "options") + private PaymentOptions options; + + /** + * Expiration for this request, in ISO 8601 duration format (e.g., 'P1D'). + */ + @JsonProperty(value = "expires") + private String expires; + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the methodData value. + * + * @return the methodData value + */ + public List getMethodData() { + return this.methodData; + } + + /** + * Set the methodData value. + * + * @param withMethodData the methodData value to set + */ + public void setMethodData(List withMethodData) { + this.methodData = withMethodData; + } + + /** + * Get the details value. + * + * @return the details value + */ + public PaymentDetails getDetails() { + return this.details; + } + + /** + * Set the details value. + * + * @param withDetails the details value to set + */ + public void setDetails(PaymentDetails withDetails) { + this.details = withDetails; + } + + /** + * Get the options value. + * + * @return the options value + */ + public PaymentOptions getOptions() { + return this.options; + } + + /** + * Set the options value. + * + * @param withOptions the options value to set + */ + public void setOptions(PaymentOptions withOptions) { + this.options = withOptions; + } + + /** + * Get the expires value. + * + * @return the expires value + */ + public String getExpires() { + return this.expires; + } + + /** + * Set the expires value. + * + * @param withExpires the expires value to set + */ + public void setExpires(String withExpires) { + this.expires = withExpires; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestComplete.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestComplete.java similarity index 53% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestComplete.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestComplete.java index cb75350c1..253a2299f 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestComplete.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestComplete.java @@ -1,97 +1,86 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Payload delivered when completing a payment request. - */ -public class PaymentRequestComplete { - /** - * Payment request ID. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Initial payment request. - */ - @JsonProperty(value = "paymentRequest") - private PaymentRequest paymentRequest; - - /** - * Corresponding payment response. - */ - @JsonProperty(value = "paymentResponse") - private PaymentResponse paymentResponse; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the PaymentRequestComplete object itself. - */ - public PaymentRequestComplete withId(String id) { - this.id = id; - return this; - } - - /** - * Get the paymentRequest value. - * - * @return the paymentRequest value - */ - public PaymentRequest paymentRequest() { - return this.paymentRequest; - } - - /** - * Set the paymentRequest value. - * - * @param paymentRequest the paymentRequest value to set - * @return the PaymentRequestComplete object itself. - */ - public PaymentRequestComplete withPaymentRequest(PaymentRequest paymentRequest) { - this.paymentRequest = paymentRequest; - return this; - } - - /** - * Get the paymentResponse value. - * - * @return the paymentResponse value - */ - public PaymentResponse paymentResponse() { - return this.paymentResponse; - } - - /** - * Set the paymentResponse value. - * - * @param paymentResponse the paymentResponse value to set - * @return the PaymentRequestComplete object itself. - */ - public PaymentRequestComplete withPaymentResponse(PaymentResponse paymentResponse) { - this.paymentResponse = paymentResponse; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Payload delivered when completing a payment request. + */ +public class PaymentRequestComplete { + /** + * Payment request ID. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Initial payment request. + */ + @JsonProperty(value = "paymentRequest") + private PaymentRequest paymentRequest; + + /** + * Corresponding payment response. + */ + @JsonProperty(value = "paymentResponse") + private PaymentResponse paymentResponse; + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the paymentRequest value. + * + * @return the paymentRequest value + */ + public PaymentRequest getPaymentRequest() { + return this.paymentRequest; + } + + /** + * Set the paymentRequest value. + * + * @param withPaymentRequest the paymentRequest value to set + */ + public void setPaymentRequest(PaymentRequest withPaymentRequest) { + this.paymentRequest = withPaymentRequest; + } + + /** + * Get the paymentResponse value. + * + * @return the paymentResponse value + */ + public PaymentResponse getPaymentResponse() { + return this.paymentResponse; + } + + /** + * Set the paymentResponse value. + * + * @param withPaymentResponse the paymentResponse value to set + */ + public void setPaymentResponse(PaymentResponse withPaymentResponse) { + this.paymentResponse = withPaymentResponse; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestCompleteResult.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestCompleteResult.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestCompleteResult.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestCompleteResult.java index fc89d4f3a..293127c72 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestCompleteResult.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestCompleteResult.java @@ -1,45 +1,38 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Result from a completed payment request. - */ -public class PaymentRequestCompleteResult { - /** - * Result of the payment request completion. - */ - @JsonProperty(value = "result") - private String result; - - /** - * Get the result value. - * - * @return the result value - */ - public String result() { - return this.result; - } - - /** - * Set the result value. - * - * @param result the result value to set - * @return the PaymentRequestCompleteResult object itself. - */ - public PaymentRequestCompleteResult withResult(String result) { - this.result = result; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Result from a completed payment request. + */ +public class PaymentRequestCompleteResult { + /** + * Result of the payment request completion. + */ + @JsonProperty(value = "result") + private String result; + + /** + * Get the result value. + * + * @return the result value + */ + public String getResult() { + return this.result; + } + + /** + * Set the result value. + * + * @param withResult the result value to set + */ + public void setResult(String withResult) { + this.result = withResult; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdate.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdate.java similarity index 52% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdate.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdate.java index 316ddcfa6..de091e0b5 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdate.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdate.java @@ -1,123 +1,110 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An update to a payment request. - */ -public class PaymentRequestUpdate { - /** - * ID for the payment request to update. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Update payment details. - */ - @JsonProperty(value = "details") - private PaymentDetails details; - - /** - * Updated shipping address. - */ - @JsonProperty(value = "shippingAddress") - private PaymentAddress shippingAddress; - - /** - * Updated shipping options. - */ - @JsonProperty(value = "shippingOption") - private String shippingOption; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the PaymentRequestUpdate object itself. - */ - public PaymentRequestUpdate withId(String id) { - this.id = id; - return this; - } - - /** - * Get the details value. - * - * @return the details value - */ - public PaymentDetails details() { - return this.details; - } - - /** - * Set the details value. - * - * @param details the details value to set - * @return the PaymentRequestUpdate object itself. - */ - public PaymentRequestUpdate withDetails(PaymentDetails details) { - this.details = details; - return this; - } - - /** - * Get the shippingAddress value. - * - * @return the shippingAddress value - */ - public PaymentAddress shippingAddress() { - return this.shippingAddress; - } - - /** - * Set the shippingAddress value. - * - * @param shippingAddress the shippingAddress value to set - * @return the PaymentRequestUpdate object itself. - */ - public PaymentRequestUpdate withShippingAddress(PaymentAddress shippingAddress) { - this.shippingAddress = shippingAddress; - return this; - } - - /** - * Get the shippingOption value. - * - * @return the shippingOption value - */ - public String shippingOption() { - return this.shippingOption; - } - - /** - * Set the shippingOption value. - * - * @param shippingOption the shippingOption value to set - * @return the PaymentRequestUpdate object itself. - */ - public PaymentRequestUpdate withShippingOption(String shippingOption) { - this.shippingOption = shippingOption; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An update to a payment request. + */ +public class PaymentRequestUpdate { + /** + * ID for the payment request to update. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Update payment details. + */ + @JsonProperty(value = "details") + private PaymentDetails details; + + /** + * Updated shipping address. + */ + @JsonProperty(value = "shippingAddress") + private PaymentAddress shippingAddress; + + /** + * Updated shipping options. + */ + @JsonProperty(value = "shippingOption") + private String shippingOption; + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the details value. + * + * @return the details value + */ + public PaymentDetails getDetails() { + return this.details; + } + + /** + * Set the details value. + * + * @param withDetails the details value to set + */ + public void setDetails(PaymentDetails withDetails) { + this.details = withDetails; + } + + /** + * Get the shippingAddress value. + * + * @return the shippingAddress value + */ + public PaymentAddress getShippingAddress() { + return this.shippingAddress; + } + + /** + * Set the shippingAddress value. + * + * @param withShippingAddress the shippingAddress value to set + */ + public void setShippingAddress(PaymentAddress withShippingAddress) { + this.shippingAddress = withShippingAddress; + } + + /** + * Get the shippingOption value. + * + * @return the shippingOption value + */ + public String getShippingOption() { + return this.shippingOption; + } + + /** + * Set the shippingOption value. + * + * @param withShippingOption the shippingOption value to set + */ + public void setShippingOption(String withShippingOption) { + this.shippingOption = withShippingOption; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdateResult.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdateResult.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdateResult.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdateResult.java index 9f0552f20..3fa22fc8c 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentRequestUpdateResult.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentRequestUpdateResult.java @@ -1,45 +1,38 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A result object from a Payment Request Update invoke operation. - */ -public class PaymentRequestUpdateResult { - /** - * Update payment details. - */ - @JsonProperty(value = "details") - private PaymentDetails details; - - /** - * Get the details value. - * - * @return the details value - */ - public PaymentDetails details() { - return this.details; - } - - /** - * Set the details value. - * - * @param details the details value to set - * @return the PaymentRequestUpdateResult object itself. - */ - public PaymentRequestUpdateResult withDetails(PaymentDetails details) { - this.details = details; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A result object from a Payment Request Update invoke operation. + */ +public class PaymentRequestUpdateResult { + /** + * Update payment details. + */ + @JsonProperty(value = "details") + private PaymentDetails details; + + /** + * Get the details value. + * + * @return the details value + */ + public PaymentDetails getDetails() { + return this.details; + } + + /** + * Set the details value. + * + * @param withDetails the details value to set + */ + public void setDetails(PaymentDetails withDetails) { + this.details = withDetails; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentResponse.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentResponse.java similarity index 62% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentResponse.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentResponse.java index 85287f200..104baf1dd 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentResponse.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentResponse.java @@ -1,187 +1,171 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A PaymentResponse is returned when a user has selected a payment method and - * approved a payment request. - */ -public class PaymentResponse { - /** - * The payment method identifier for the payment method that the user - * selected to fulfil the transaction. - */ - @JsonProperty(value = "methodName") - private String methodName; - - /** - * A JSON-serializable object that provides a payment method specific - * message used by the merchant to process the transaction and determine - * successful fund transfer. - */ - @JsonProperty(value = "details") - private Object details; - - /** - * If the requestShipping flag was set to true in the PaymentOptions passed - * to the PaymentRequest constructor, then shippingAddress will be the full - * and final shipping address chosen by the user. - */ - @JsonProperty(value = "shippingAddress") - private PaymentAddress shippingAddress; - - /** - * If the requestShipping flag was set to true in the PaymentOptions passed - * to the PaymentRequest constructor, then shippingOption will be the id - * attribute of the selected shipping option. - */ - @JsonProperty(value = "shippingOption") - private String shippingOption; - - /** - * If the requestPayerEmail flag was set to true in the PaymentOptions - * passed to the PaymentRequest constructor, then payerEmail will be the - * email address chosen by the user. - */ - @JsonProperty(value = "payerEmail") - private String payerEmail; - - /** - * If the requestPayerPhone flag was set to true in the PaymentOptions - * passed to the PaymentRequest constructor, then payerPhone will be the - * phone number chosen by the user. - */ - @JsonProperty(value = "payerPhone") - private String payerPhone; - - /** - * Get the methodName value. - * - * @return the methodName value - */ - public String methodName() { - return this.methodName; - } - - /** - * Set the methodName value. - * - * @param methodName the methodName value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withMethodName(String methodName) { - this.methodName = methodName; - return this; - } - - /** - * Get the details value. - * - * @return the details value - */ - public Object details() { - return this.details; - } - - /** - * Set the details value. - * - * @param details the details value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withDetails(Object details) { - this.details = details; - return this; - } - - /** - * Get the shippingAddress value. - * - * @return the shippingAddress value - */ - public PaymentAddress shippingAddress() { - return this.shippingAddress; - } - - /** - * Set the shippingAddress value. - * - * @param shippingAddress the shippingAddress value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withShippingAddress(PaymentAddress shippingAddress) { - this.shippingAddress = shippingAddress; - return this; - } - - /** - * Get the shippingOption value. - * - * @return the shippingOption value - */ - public String shippingOption() { - return this.shippingOption; - } - - /** - * Set the shippingOption value. - * - * @param shippingOption the shippingOption value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withShippingOption(String shippingOption) { - this.shippingOption = shippingOption; - return this; - } - - /** - * Get the payerEmail value. - * - * @return the payerEmail value - */ - public String payerEmail() { - return this.payerEmail; - } - - /** - * Set the payerEmail value. - * - * @param payerEmail the payerEmail value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withPayerEmail(String payerEmail) { - this.payerEmail = payerEmail; - return this; - } - - /** - * Get the payerPhone value. - * - * @return the payerPhone value - */ - public String payerPhone() { - return this.payerPhone; - } - - /** - * Set the payerPhone value. - * - * @param payerPhone the payerPhone value to set - * @return the PaymentResponse object itself. - */ - public PaymentResponse withPayerPhone(String payerPhone) { - this.payerPhone = payerPhone; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A PaymentResponse is returned when a user has selected a payment method and + * approved a payment request. + */ +public class PaymentResponse { + /** + * The payment method identifier for the payment method that the user + * selected to fulfil the transaction. + */ + @JsonProperty(value = "methodName") + private String methodName; + + /** + * A JSON-serializable object that provides a payment method specific + * message used by the merchant to process the transaction and determine + * successful fund transfer. + */ + @JsonProperty(value = "details") + private Object details; + + /** + * If the requestShipping flag was set to true in the PaymentOptions passed + * to the PaymentRequest constructor, then shippingAddress will be the full + * and final shipping address chosen by the user. + */ + @JsonProperty(value = "shippingAddress") + private PaymentAddress shippingAddress; + + /** + * If the requestShipping flag was set to true in the PaymentOptions passed + * to the PaymentRequest constructor, then shippingOption will be the id + * attribute of the selected shipping option. + */ + @JsonProperty(value = "shippingOption") + private String shippingOption; + + /** + * If the requestPayerEmail flag was set to true in the PaymentOptions + * passed to the PaymentRequest constructor, then payerEmail will be the + * email address chosen by the user. + */ + @JsonProperty(value = "payerEmail") + private String payerEmail; + + /** + * If the requestPayerPhone flag was set to true in the PaymentOptions + * passed to the PaymentRequest constructor, then payerPhone will be the + * phone number chosen by the user. + */ + @JsonProperty(value = "payerPhone") + private String payerPhone; + + /** + * Get the methodName value. + * + * @return the methodName value + */ + public String getMethodName() { + return this.methodName; + } + + /** + * Set the methodName value. + * + * @param withMethodName the methodName value to set + */ + public void setMethodName(String withMethodName) { + this.methodName = withMethodName; + } + + /** + * Get the details value. + * + * @return the details value + */ + public Object getDetails() { + return this.details; + } + + /** + * Set the details value. + * + * @param withDetails the details value to set + */ + public void setDetails(Object withDetails) { + this.details = withDetails; + } + + /** + * Get the shippingAddress value. + * + * @return the shippingAddress value + */ + public PaymentAddress getShippingAddress() { + return this.shippingAddress; + } + + /** + * Set the shippingAddress value. + * + * @param withShippingAddress the shippingAddress value to set + */ + public void setShippingAddress(PaymentAddress withShippingAddress) { + this.shippingAddress = withShippingAddress; + } + + /** + * Get the shippingOption value. + * + * @return the shippingOption value + */ + public String getShippingOption() { + return this.shippingOption; + } + + /** + * Set the shippingOption value. + * + * @param withShippingOption the shippingOption value to set + */ + public void setShippingOption(String withShippingOption) { + this.shippingOption = withShippingOption; + } + + /** + * Get the payerEmail value. + * + * @return the payerEmail value + */ + public String getPayerEmail() { + return this.payerEmail; + } + + /** + * Set the payerEmail value. + * + * @param withPayerEmail the payerEmail value to set + */ + public void setPayerEmail(String withPayerEmail) { + this.payerEmail = withPayerEmail; + } + + /** + * Get the payerPhone value. + * + * @return the payerPhone value + */ + public String getPayerPhone() { + return this.payerPhone; + } + + /** + * Set the payerPhone value. + * + * @param withPayerPhone the payerPhone value to set + * @return the PaymentResponse object itself. + */ + public void setPayerPhone(String withPayerPhone) { + this.payerPhone = withPayerPhone; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentShippingOption.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentShippingOption.java similarity index 53% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentShippingOption.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentShippingOption.java index 76a4da913..06df2964a 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/PaymentShippingOption.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/PaymentShippingOption.java @@ -1,123 +1,110 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Describes a shipping option. - */ -public class PaymentShippingOption { - /** - * String identifier used to reference this PaymentShippingOption. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Human-readable description of the item. - */ - @JsonProperty(value = "label") - private String label; - - /** - * Contains the monetary amount for the item. - */ - @JsonProperty(value = "amount") - private PaymentCurrencyAmount amount; - - /** - * Indicates whether this is the default selected PaymentShippingOption. - */ - @JsonProperty(value = "selected") - private Boolean selected; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the PaymentShippingOption object itself. - */ - public PaymentShippingOption withId(String id) { - this.id = id; - return this; - } - - /** - * Get the label value. - * - * @return the label value - */ - public String label() { - return this.label; - } - - /** - * Set the label value. - * - * @param label the label value to set - * @return the PaymentShippingOption object itself. - */ - public PaymentShippingOption withLabel(String label) { - this.label = label; - return this; - } - - /** - * Get the amount value. - * - * @return the amount value - */ - public PaymentCurrencyAmount amount() { - return this.amount; - } - - /** - * Set the amount value. - * - * @param amount the amount value to set - * @return the PaymentShippingOption object itself. - */ - public PaymentShippingOption withAmount(PaymentCurrencyAmount amount) { - this.amount = amount; - return this; - } - - /** - * Get the selected value. - * - * @return the selected value - */ - public Boolean selected() { - return this.selected; - } - - /** - * Set the selected value. - * - * @param selected the selected value to set - * @return the PaymentShippingOption object itself. - */ - public PaymentShippingOption withSelected(Boolean selected) { - this.selected = selected; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Describes a shipping option. + */ +public class PaymentShippingOption { + /** + * String identifier used to reference this PaymentShippingOption. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Human-readable description of the item. + */ + @JsonProperty(value = "label") + private String label; + + /** + * Contains the monetary amount for the item. + */ + @JsonProperty(value = "amount") + private PaymentCurrencyAmount amount; + + /** + * Indicates whether this is the default selected PaymentShippingOption. + */ + @JsonProperty(value = "selected") + private boolean selected; + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Get the label value. + * + * @return the label value + */ + public String getLabel() { + return this.label; + } + + /** + * Set the label value. + * + * @param withLabel the label value to set + */ + public void setLabel(String withLabel) { + this.label = withLabel; + } + + /** + * Get the amount value. + * + * @return the amount value + */ + public PaymentCurrencyAmount getAmount() { + return this.amount; + } + + /** + * Set the amount value. + * + * @param withAmount the amount value to set + */ + public void setAmount(PaymentCurrencyAmount withAmount) { + this.amount = withAmount; + } + + /** + * Get the selected value. + * + * @return the selected value + */ + public boolean getSelected() { + return this.selected; + } + + /** + * Set the selected value. + * + * @param withSelected the selected value to set + */ + public void setSelected(boolean withSelected) { + this.selected = withSelected; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Place.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Place.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Place.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Place.java index ebe70fa2d..c38971be8 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Place.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Place.java @@ -1,150 +1,132 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.microsoft.bot.schema.EntityImpl; - -/** - * Place (entity type: "https://schema.org/Place"). - */ -public class Place extends EntityImpl { - /** - * Address of the place (may be `string` or complex object of type - * `PostalAddress`). - */ - @JsonProperty(value = "address") - private Object address; - - /** - * Geo coordinates of the place (may be complex object of type - * `GeoCoordinates` or `GeoShape`). - */ - @JsonProperty(value = "geo") - private Object geo; - - /** - * Map to the place (may be `string` (URL) or complex object of type - * `Map`). - */ - @JsonProperty(value = "hasMap") - private Object hasMap; - - /** - * The type of the thing. - */ - @JsonProperty(value = "type") - private String type; - - /** - * The name of the thing. - */ - @JsonProperty(value = "name") - private String name; - - /** - * Get the address value. - * - * @return the address value - */ - public Object address() { - return this.address; - } - - /** - * Set the address value. - * - * @param address the address value to set - * @return the Place object itself. - */ - public Place withAddress(Object address) { - this.address = address; - return this; - } - - /** - * Get the geo value. - * - * @return the geo value - */ - public Object geo() { - return this.geo; - } - - /** - * Set the geo value. - * - * @param geo the geo value to set - * @return the Place object itself. - */ - public Place withGeo(Object geo) { - this.geo = geo; - return this; - } - - /** - * Get the hasMap value. - * - * @return the hasMap value - */ - public Object hasMap() { - return this.hasMap; - } - - /** - * Set the hasMap value. - * - * @param hasMap the hasMap value to set - * @return the Place object itself. - */ - public Place withHasMap(Object hasMap) { - this.hasMap = hasMap; - return this; - } - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Place object itself. - */ - public Place withType(String type) { - this.type = type; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the Place object itself. - */ - public Place withName(String name) { - this.name = name; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Place (entity type: "https://schema.org/Place"). + */ +public class Place implements EntitySerialization { + /** + * Address of the place (may be `string` or complex object of type + * `PostalAddress`). + */ + @JsonProperty(value = "address") + private Object address; + + /** + * Geo coordinates of the place (may be complex object of type + * `GeoCoordinates` or `GeoShape`). + */ + @JsonProperty(value = "geo") + private Object geo; + + /** + * Map to the place (may be `string` (URL) or complex object of type + * `Map`). + */ + @JsonProperty(value = "hasMap") + private Object hasMap; + + /** + * The type of the thing. + */ + @JsonProperty(value = "type") + private String type; + + /** + * The name of the thing. + */ + @JsonProperty(value = "name") + private String name; + + public Place() { + this.type = "Place"; + } + + /** + * Get the address value. + * + * @return the address value + */ + public Object getAddress() { + return this.address; + } + + /** + * Set the address value. + * + * @param withAddress the address value to set + */ + public void setAddress(Object withAddress) { + this.address = withAddress; + } + + /** + * Get the geo value. + * + * @return the geo value + */ + public Object getGeo() { + return this.geo; + } + + /** + * Set the geo value. + * + * @param withGeo the geo value to set + */ + public void setGeo(Object withGeo) { + this.geo = withGeo; + } + + /** + * Get the hasMap value. + * + * @return the hasMap value + */ + public Object getHasMap() { + return this.hasMap; + } + + /** + * Set the hasMap value. + * + * @param withHasMap the hasMap value to set + */ + public void setHasMap(Object withHasMap) { + this.hasMap = withHasMap; + } + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptCard.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptCard.java index d2ea2f1ba..8c8c5298d 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptCard.java @@ -1,228 +1,210 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A receipt card. - */ -public class ReceiptCard { - /** - * Title of the card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Array of Fact objects. - */ - @JsonProperty(value = "facts") - private List facts; - - /** - * Array of Receipt Items. - */ - @JsonProperty(value = "items") - private List items; - - /** - * This action will be activated when user taps on the card. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Total amount of money paid (or to be paid). - */ - @JsonProperty(value = "total") - private String total; - - /** - * Total amount of tax paid (or to be paid). - */ - @JsonProperty(value = "tax") - private String tax; - - /** - * Total amount of VAT paid (or to be paid). - */ - @JsonProperty(value = "vat") - private String vat; - - /** - * Set of actions applicable to the current card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the facts value. - * - * @return the facts value - */ - public List facts() { - return this.facts; - } - - /** - * Set the facts value. - * - * @param facts the facts value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withFacts(List facts) { - this.facts = facts; - return this; - } - - /** - * Get the items value. - * - * @return the items value - */ - public List items() { - return this.items; - } - - /** - * Set the items value. - * - * @param items the items value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withItems(List items) { - this.items = items; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withTap(CardAction tap) { - this.tap = tap; - return this; - } - - /** - * Get the total value. - * - * @return the total value - */ - public String total() { - return this.total; - } - - /** - * Set the total value. - * - * @param total the total value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withTotal(String total) { - this.total = total; - return this; - } - - /** - * Get the tax value. - * - * @return the tax value - */ - public String tax() { - return this.tax; - } - - /** - * Set the tax value. - * - * @param tax the tax value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withTax(String tax) { - this.tax = tax; - return this; - } - - /** - * Get the vat value. - * - * @return the vat value - */ - public String vat() { - return this.vat; - } - - /** - * Set the vat value. - * - * @param vat the vat value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withVat(String vat) { - this.vat = vat; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the ReceiptCard object itself. - */ - public ReceiptCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A receipt card. + */ +public class ReceiptCard { + /** + * Title of the card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Array of Fact objects. + */ + @JsonProperty(value = "facts") + private List facts; + + /** + * Array of Receipt Items. + */ + @JsonProperty(value = "items") + private List items; + + /** + * This action will be activated when user taps on the card. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Total amount of money paid (or to be paid). + */ + @JsonProperty(value = "total") + private String total; + + /** + * Total amount of tax paid (or to be paid). + */ + @JsonProperty(value = "tax") + private String tax; + + /** + * Total amount of VAT paid (or to be paid). + */ + @JsonProperty(value = "vat") + private String vat; + + /** + * Set of actions applicable to the current card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the facts value. + * + * @return the facts value + */ + public List getFacts() { + return this.facts; + } + + /** + * Set the facts value. + * + * @param withFacts the facts value to set + */ + public void setFacts(List withFacts) { + this.facts = withFacts; + } + + /** + * Get the items value. + * + * @return the items value + */ + public List getItems() { + return this.items; + } + + /** + * Set the items value. + * + * @param withItems the items value to set + */ + public void setItems(List withItems) { + this.items = withItems; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction getTap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } + + /** + * Get the total value. + * + * @return the total value + */ + public String getTotal() { + return this.total; + } + + /** + * Set the total value. + * + * @param withTotal the total value to set + */ + public void setTotal(String withTotal) { + this.total = withTotal; + } + + /** + * Get the tax value. + * + * @return the tax value + */ + public String geTax() { + return this.tax; + } + + /** + * Set the tax value. + * + * @param withTax the tax value to set + * @return the ReceiptCard object itself. + */ + public void setTax(String withTax) { + this.tax = withTax; + } + + /** + * Get the vat value. + * + * @return the vat value + */ + public String getVat() { + return this.vat; + } + + /** + * Set the vat value. + * + * @param withVat the vat value to set + */ + public void setVat(String withVat) { + this.vat = withVat; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + * @return the ReceipCard object itself. + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptItem.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptItem.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptItem.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptItem.java index d99390668..fb52f7dfb 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ReceiptItem.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ReceiptItem.java @@ -1,203 +1,184 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An item on a receipt card. - */ -public class ReceiptItem { - /** - * Title of the Card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle appears just below Title field, differs from Title in font - * styling only. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text field appears just below subtitle, differs from Subtitle in font - * styling only. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Image. - */ - @JsonProperty(value = "image") - private CardImage image; - - /** - * Amount with currency. - */ - @JsonProperty(value = "price") - private String price; - - /** - * Number of items of given kind. - */ - @JsonProperty(value = "quantity") - private String quantity; - - /** - * This action will be activated when user taps on the Item bubble. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withText(String text) { - this.text = text; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public CardImage image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withImage(CardImage image) { - this.image = image; - return this; - } - - /** - * Get the price value. - * - * @return the price value - */ - public String price() { - return this.price; - } - - /** - * Set the price value. - * - * @param price the price value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withPrice(String price) { - this.price = price; - return this; - } - - /** - * Get the quantity value. - * - * @return the quantity value - */ - public String quantity() { - return this.quantity; - } - - /** - * Set the quantity value. - * - * @param quantity the quantity value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withQuantity(String quantity) { - this.quantity = quantity; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the ReceiptItem object itself. - */ - public ReceiptItem withTap(CardAction tap) { - this.tap = tap; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An item on a receipt card. + */ +public class ReceiptItem { + /** + * Title of the Card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle appears just below Title field, differs from Title in font + * styling only. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text field appears just below subtitle, differs from Subtitle in font + * styling only. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Image. + */ + @JsonProperty(value = "image") + private CardImage image; + + /** + * Amount with currency. + */ + @JsonProperty(value = "price") + private String price; + + /** + * Number of items of given kind. + */ + @JsonProperty(value = "quantity") + private String quantity; + + /** + * This action will be activated when user taps on the Item bubble. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the image value. + * + * @return the image value + */ + public CardImage getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(CardImage withImage) { + this.image = withImage; + } + + /** + * Get the price value. + * + * @return the price value + */ + public String getPrice() { + return this.price; + } + + /** + * Set the price value. + * + * @param withPrice the price value to set + */ + public void setPrice(String withPrice) { + this.price = withPrice; + } + + /** + * Get the quantity value. + * + * @return the quantity value + */ + public String getQuantity() { + return this.quantity; + } + + /** + * Set the quantity value. + * + * @param withQuantity the quantity value to set + */ + public void setQuantity(String withQuantity) { + this.quantity = withQuantity; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction getTap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ResourceResponse.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResourceResponse.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ResourceResponse.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResourceResponse.java index 8fa7b99e4..48408a21b 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ResourceResponse.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResourceResponse.java @@ -1,45 +1,46 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A response containing a resource ID. - */ -public class ResourceResponse { - /** - * Id of the resource. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the ResourceResponse object itself. - */ - public ResourceResponse withId(String id) { - this.id = id; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A response containing a resource ID. + */ +public class ResourceResponse { + /** + * Id of the resource. + */ + @JsonProperty(value = "id") + private String id; + + public ResourceResponse(){ + + } + + public ResourceResponse(String withId) { + this.id = withId; + } + + /** + * Get the id value. + * + * @return the id value + */ + public String getId() { + return this.id; + } + + /** + * Set the id value. + * + * @param withId the id value to set + */ + public void setId(String withId) { + this.id = withId; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResultPair.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResultPair.java index b089df1b7..7f5e4d8f0 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResultPair.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ResultPair.java @@ -1,10 +1,17 @@ -package com.microsoft.bot.schema; - -public class ResultPair { - public final X x; - public final Y y; - public ResultPair(X x, Y y) { - this.x = x; - this.y = y; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +public class ResultPair { + public final X x; + public final Y y; + + public ResultPair(X withX, Y withY) { + this.x = withX; + this.y = withY; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/RoleTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/RoleTypes.java similarity index 68% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/RoleTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/RoleTypes.java index 5a4bb2104..2290a7b46 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/RoleTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/RoleTypes.java @@ -1,55 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Role of the entity behind the account (Example: User, Bot, etc.). - */ -public enum RoleTypes { - /** Enum value user. */ - USER("user"), - - /** Enum value bot. */ - BOT("bot"); - - /** The actual serialized value for a RoleTypes instance. */ - private String value; - - RoleTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a RoleTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed RoleTypes object, or null if unable to parse. - */ - @JsonCreator - public static RoleTypes fromString(String value) { - RoleTypes[] items = RoleTypes.values(); - for (RoleTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Role of the entity behind the account (Example: User, Bot, etc.). + */ +public enum RoleTypes { + /** + * Enum value user. + */ + USER("user"), + + /** + * Enum value bot. + */ + BOT("bot"); + + /** + * The actual serialized value for a RoleTypes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + RoleTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a RoleTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed RoleTypes object, or null if unable to parse. + */ + @JsonCreator + public static RoleTypes fromString(String value) { + RoleTypes[] items = RoleTypes.values(); + for (RoleTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticAction.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticAction.java similarity index 54% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticAction.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticAction.java index 419ace06d..d8a9ace85 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticAction.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticAction.java @@ -1,69 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.Map; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Represents a reference to a programmatic action - */ -public class SemanticAction { - /** - * ID of this action. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Entities associated with this action. - */ - @JsonProperty(value = "entities") - Map entities; - - /** - * Gets ID of this action. - */ - public String id(){ - return this.id; - } - - /** - * Sets ID of this action. - * - * @param id ID of this action - * @return The SemanticAction object itself. - */ - public SemanticAction withId(String id){ - this.id = id; - return this; - } - - /** - * Gets entities associated with this action. - * - * @return the activities value - */ - public Map entities() { - return this.entities; - } - - /** - * Sets entities associated with this action. - * - * @param entities - * @return The SemanticAction object itself. - */ - public SemanticAction withEntities(Map entities){ - this.entities = entities; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +/** + * Represents a reference to a programmatic action + */ +public class SemanticAction { + /** + * Entities associated with this action. + */ + @JsonProperty(value = "entities") + private Map entities; + + /** + * ID of this action. + */ + @JsonProperty(value = "id") + private String id; + + /** + * Gets ID of this action. + */ + public String getId() { + return this.id; + } + + /** + * Sets ID of this action. + * + * @param withId ID of this action + */ + public void setId(String withId) { + this.id = withId; + } + + /** + * Gets entities associated with this action. + * + * @return the activities value + */ + public Map getEntities() { + return this.entities; + } + + /** + * Sets entities associated with this action. + * + * @param withEntities + */ + public void setEntities(Map withEntities) { + this.entities = withEntities; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticActionStates.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticActionStates.java similarity index 67% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticActionStates.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticActionStates.java index 52faf7288..4faf1e31e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SemanticActionStates.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SemanticActionStates.java @@ -1,59 +1,68 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Indicates whether the semantic action is starting, continuing, or done. - */ -public enum SemanticActionStates { - /** Enum value start. */ - START("start"), - - /** Enum value continue. */ - CONTINUE("continue"), - - /** Enum value done. */ - DONE("done"); - - - /** The actual serialized value for a SemanticActionStates instance. */ - private String value; - - SemanticActionStates(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a ActivityTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed ActivityTypes object, or null if unable to parse. - */ - @JsonCreator - public static SemanticActionStates fromString(String value) { - SemanticActionStates[] items = SemanticActionStates.values(); - for (SemanticActionStates item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Indicates whether the semantic action is starting, continuing, or done. + */ +public enum SemanticActionStates { + /** + * Enum value start. + */ + START("start"), + + /** + * Enum value continue. + */ + CONTINUE("continue"), + + /** + * Enum value done. + */ + DONE("done"); + + + /** + * The actual serialized value for a SemanticActionStates instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + SemanticActionStates(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a ActivityTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed ActivityTypes object, or null if unable to parse. + */ + @JsonCreator + public static SemanticActionStates fromString(String value) { + SemanticActionStates[] items = SemanticActionStates.values(); + for (SemanticActionStates item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SigninCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SigninCard.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SigninCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SigninCard.java index a9d448111..784705a73 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SigninCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SigninCard.java @@ -1,72 +1,64 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A card representing a request to sign in. - */ -public class SigninCard { - /** - * Text for signin request. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Action to use to perform signin. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the SigninCard object itself. - */ - public SigninCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the SigninCard object itself. - */ - public SigninCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A card representing a request to sign in. + */ +public class SigninCard { + /** + * Text for signin request. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Action to use to perform signin. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SuggestedActions.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java similarity index 58% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SuggestedActions.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java index 22b7ca21f..58e0361ec 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/SuggestedActions.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java @@ -1,74 +1,66 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * SuggestedActions that can be performed. - */ -public class SuggestedActions { - /** - * Ids of the recipients that the actions should be shown to. These Ids - * are relative to the channelId and a subset of all recipients of the - * activity. - */ - @JsonProperty(value = "to") - private List to; - - /** - * Actions that can be shown to the user. - */ - @JsonProperty(value = "actions") - private List actions; - - /** - * Get the to value. - * - * @return the to value - */ - public List to() { - return this.to; - } - - /** - * Set the to value. - * - * @param to the to value to set - * @return the SuggestedActions object itself. - */ - public SuggestedActions withTo(List to) { - this.to = to; - return this; - } - - /** - * Get the actions value. - * - * @return the actions value - */ - public List actions() { - return this.actions; - } - - /** - * Set the actions value. - * - * @param actions the actions value to set - * @return the SuggestedActions object itself. - */ - public SuggestedActions withActions(List actions) { - this.actions = actions; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * SuggestedActions that can be performed. + */ +public class SuggestedActions { + /** + * Ids of the recipients that the actions should be shown to. These Ids + * are relative to the channelId and a subset of all recipients of the + * activity. + */ + @JsonProperty(value = "to") + private List to; + + /** + * Actions that can be shown to the user. + */ + @JsonProperty(value = "actions") + private List actions; + + /** + * Get the to value. + * + * @return the to value + */ + public List getTo() { + return this.to; + } + + /** + * Set the to value. + * + * @param withTo the to value to set + */ + public void setTo(List withTo) { + this.to = withTo; + } + + /** + * Get the actions value. + * + * @return the actions value + */ + public List getActions() { + return this.actions; + } + + /** + * Set the actions value. + * + * @param withActions the actions value to set + */ + public void setActions(List withActions) { + this.actions = withActions; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextFormatTypes.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextFormatTypes.java similarity index 67% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextFormatTypes.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextFormatTypes.java index 8995059d3..e051eefa2 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextFormatTypes.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextFormatTypes.java @@ -1,58 +1,67 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Defines values for TextFormatTypes. - */ -public enum TextFormatTypes { - /** Enum value markdown. */ - MARKDOWN("markdown"), - - /** Enum value plain. */ - PLAIN("plain"), - - /** Enum value xml. */ - XML("xml"); - - /** The actual serialized value for a TextFormatTypes instance. */ - private String value; - - TextFormatTypes(String value) { - this.value = value; - } - - /** - * Parses a serialized value to a TextFormatTypes instance. - * - * @param value the serialized value to parse. - * @return the parsed TextFormatTypes object, or null if unable to parse. - */ - @JsonCreator - public static TextFormatTypes fromString(String value) { - TextFormatTypes[] items = TextFormatTypes.values(); - for (TextFormatTypes item : items) { - if (item.toString().equalsIgnoreCase(value)) { - return item; - } - } - return null; - } - - @JsonValue - @Override - public String toString() { - return this.value; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Defines values for TextFormatTypes. + */ +public enum TextFormatTypes { + /** + * Enum value markdown. + */ + MARKDOWN("markdown"), + + /** + * Enum value plain. + */ + PLAIN("plain"), + + /** + * Enum value xml. + */ + XML("xml"); + + /** + * The actual serialized value for a TextFormatTypes instance. + */ + private String value; + + /** + * Creates a ActionTypes enum from a string. + * @param withValue The string value. Should be a valid enum value. + * @throws IllegalArgumentException If the string doesn't match a valid value. + */ + TextFormatTypes(String withValue) { + this.value = withValue; + } + + /** + * Parses a serialized value to a TextFormatTypes instance. + * + * @param value the serialized value to parse. + * @return the parsed TextFormatTypes object, or null if unable to parse. + */ + @JsonCreator + public static TextFormatTypes fromString(String value) { + TextFormatTypes[] items = TextFormatTypes.values(); + for (TextFormatTypes item : items) { + if (item.toString().equalsIgnoreCase(value)) { + return item; + } + } + return null; + } + + @JsonValue + @Override + public String toString() { + return this.value; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextHighlight.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextHighlight.java similarity index 57% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextHighlight.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextHighlight.java index c7653a209..11a7ce9da 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TextHighlight.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TextHighlight.java @@ -1,71 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Refers to a substring of content within another field. - */ -public class TextHighlight { - /** - * Defines the snippet of text to highlight. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Occurrence of the text field within the referenced text, if multiple exist. - */ - @JsonProperty(value = "occurence") - private Integer occurence; - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the TextHighlight object itself. - */ - public TextHighlight withText(String text) { - this.text = text; - return this; - } - - /** - * Get the occurence value. - * - * @return the occurence value - */ - public Integer occurence() { - return this.occurence; - } - - /** - * Set the occurence value. - * - * @param occurence the occurence value to set - * @return the TextHighlight object itself. - */ - public TextHighlight withOccurence(Integer occurence) { - this.occurence = occurence; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Refers to a substring of content within another field. + */ +public class TextHighlight { + /** + * Defines the snippet of text to highlight. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Occurrence of the text field within the referenced text, if multiple exist. + */ + @JsonProperty(value = "occurence") + private Integer occurence; + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the occurence value. + * + * @return the occurence value + */ + public Integer getOccurence() { + return this.occurence; + } + + /** + * Set the occurence value. + * + * @param withOccurence the occurence value to set + */ + public void setOccurence(Integer withOccurence) { + this.occurence = withOccurence; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Thing.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Thing.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Thing.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Thing.java index c9b7da63c..2e14d9d8a 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Thing.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Thing.java @@ -1,71 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Thing (entity type: "https://schema.org/Thing"). - */ -public class Thing { - /** - * The type of the thing. - */ - @JsonProperty(value = "type") - private String type; - - /** - * The name of the thing. - */ - @JsonProperty(value = "name") - private String name; - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Thing object itself. - */ - public Thing withType(String type) { - this.type = type; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the Thing object itself. - */ - public Thing withName(String name) { - this.name = name; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Thing (entity type: "https://schema.org/Thing"). + */ +public class Thing { + /** + * The type of the thing. + */ + @JsonProperty(value = "type") + private String type; + + /** + * The name of the thing. + */ + @JsonProperty(value = "name") + private String name; + + /** + * Get the type value. + * + * @return the type value + */ + public String getType() { + return this.type; + } + + /** + * Set the type value. + * + * @param withType the type value to set + */ + public void setType(String withType) { + this.type = withType; + } + + /** + * Get the name value. + * + * @return the name value + */ + public String getName() { + return this.name; + } + + /** + * Set the name value. + * + * @param withName the name value to set + */ + public void setName(String withName) { + this.name = withName; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailCard.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailCard.java index e1fb99cd8..684c88a61 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailCard.java @@ -1,176 +1,160 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A thumbnail card (card with a single, small thumbnail image). - */ -public class ThumbnailCard { - /** - * Title of the card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of the card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text for the card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Array of images for the card. - */ - @JsonProperty(value = "images") - private List images; - - /** - * Set of actions applicable to the current card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This action will be activated when user taps on the card itself. - */ - @JsonProperty(value = "tap") - private CardAction tap; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the images value. - * - * @return the images value - */ - public List images() { - return this.images; - } - - /** - * Set the images value. - * - * @param images the images value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withImages(List images) { - this.images = images; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the tap value. - * - * @return the tap value - */ - public CardAction tap() { - return this.tap; - } - - /** - * Set the tap value. - * - * @param tap the tap value to set - * @return the ThumbnailCard object itself. - */ - public ThumbnailCard withTap(CardAction tap) { - this.tap = tap; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A thumbnail card (card with a single, small thumbnail image). + */ +public class ThumbnailCard { + /** + * Title of the card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of the card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text for the card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Array of images for the card. + */ + @JsonProperty(value = "images") + private List images; + + /** + * Set of actions applicable to the current card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This action will be activated when user taps on the card itself. + */ + @JsonProperty(value = "tap") + private CardAction tap; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the images value. + * + * @return the images value + */ + public List getImages() { + return this.images; + } + + /** + * Set the images value. + * + * @param withImages the images value to set + */ + public void setImages(List withImages) { + this.images = withImages; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the tap value. + * + * @return the tap value + */ + public CardAction getTap() { + return this.tap; + } + + /** + * Set the tap value. + * + * @param withTap the tap value to set + */ + public void setTap(CardAction withTap) { + this.tap = withTap; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailUrl.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailUrl.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailUrl.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailUrl.java index 9e40a7c44..7c115c0f6 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ThumbnailUrl.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ThumbnailUrl.java @@ -1,71 +1,62 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Thumbnail URL. - */ -public class ThumbnailUrl { - /** - * URL pointing to the thumbnail to use for media content. - */ - @JsonProperty(value = "url") - private String url; - - /** - * HTML alt text to include on this thumbnail image. - */ - @JsonProperty(value = "alt") - private String alt; - - /** - * Get the url value. - * - * @return the url value - */ - public String url() { - return this.url; - } - - /** - * Set the url value. - * - * @param url the url value to set - * @return the ThumbnailUrl object itself. - */ - public ThumbnailUrl withUrl(String url) { - this.url = url; - return this; - } - - /** - * Get the alt value. - * - * @return the alt value - */ - public String alt() { - return this.alt; - } - - /** - * Set the alt value. - * - * @param alt the alt value to set - * @return the ThumbnailUrl object itself. - */ - public ThumbnailUrl withAlt(String alt) { - this.alt = alt; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Thumbnail URL. + */ +public class ThumbnailUrl { + /** + * URL pointing to the thumbnail to use for media content. + */ + @JsonProperty(value = "url") + private String url; + + /** + * HTML alt text to include on this thumbnail image. + */ + @JsonProperty(value = "alt") + private String alt; + + /** + * Get the url value. + * + * @return the url value + */ + public String getUrl() { + return this.url; + } + + /** + * Set the url value. + * + * @param withUrl the url value to set + */ + public void setUrl(String withUrl) { + this.url = withUrl; + } + + /** + * Get the alt value. + * + * @return the alt value + */ + public String getAlt() { + return this.alt; + } + + /** + * Set the alt value. + * + * @param withAlt the alt value to set + */ + public void setAlt(String withAlt) { + this.alt = withAlt; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenExchangeState.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenExchangeState.java index ecc145932..eda817685 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenExchangeState.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenExchangeState.java @@ -1,62 +1,70 @@ -package com.microsoft.bot.schema; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.microsoft.bot.schema.models.ConversationReference; - -/** - * State object passed to the bot token service. - */ -public class TokenExchangeState -{ - /** - * The connection name that was used - */ - @JsonProperty(value = "connectionName") - private String connectionName; - public String connectionName() { - return this.connectionName; - } - public TokenExchangeState withConnectionName(String connectionName) { - this.connectionName = connectionName; - return this; - } - - /** - * A reference to the conversation - */ - @JsonProperty(value = "conversation") - private ConversationReference conversation; - public ConversationReference conversation() { - return this.conversation; - } - public TokenExchangeState withConversation(ConversationReference conversation) { - this.conversation = conversation; - return this; - } - - /** - * The URL of the bot messaging endpoint - */ - @JsonProperty("botUrl") - private String botUrl; - public String botUrl() { - return this.botUrl; - } - public TokenExchangeState withBotUrl(String botUrl) { - this.botUrl = botUrl; - return this; - } - - /** - * The bot's registered application ID - */ - @JsonProperty("msAppId") - String msAppId; - public String msAppId() { - return this.msAppId; - } - public TokenExchangeState withMsAppId(String msAppId) { - this.msAppId = msAppId; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * State object passed to the bot token service. + */ +public class TokenExchangeState { + /** + * The bot's registered application ID + */ + @JsonProperty("msAppId") + private String msAppId; + + /** + * The connection name that was used + */ + @JsonProperty(value = "connectionName") + private String connectionName; + + /** + * A reference to the conversation + */ + @JsonProperty(value = "conversation") + private ConversationReference conversation; + + /** + * The URL of the bot messaging endpoint + */ + @JsonProperty("botUrl") + private String botUrl; + + public String getConnectionName() { + return this.connectionName; + } + + public void setConnectionName(String withConnectionName) { + this.connectionName = withConnectionName; + } + + public ConversationReference getConversation() { + return this.conversation; + } + + public void setConversation(ConversationReference withConversation) { + this.conversation = withConversation; + } + + public String getBotUrl() { + return this.botUrl; + } + + public void setBotUrl(String withBotUrl) { + this.botUrl = withBotUrl; + } + + public String getMsAppId() { + return this.msAppId; + } + + public void setMsAppId(String withMsAppId) { + this.msAppId = withMsAppId; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenRequest.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenRequest.java similarity index 56% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenRequest.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenRequest.java index ac4e043d3..ed763e1d2 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenRequest.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenRequest.java @@ -1,72 +1,64 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.Map; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A request to receive a user token. - */ -public class TokenRequest { - /** - * The provider to request a user token from. - */ - @JsonProperty(value = "provider") - private String provider; - - /** - * A collection of settings for the specific provider for this request. - */ - @JsonProperty(value = "settings") - private Map settings; - - /** - * Get the provider value. - * - * @return the provider value - */ - public String provider() { - return this.provider; - } - - /** - * Set the provider value. - * - * @param provider the provider value to set - * @return the TokenRequest object itself. - */ - public TokenRequest withProvider(String provider) { - this.provider = provider; - return this; - } - - /** - * Get the settings value. - * - * @return the settings value - */ - public Map settings() { - return this.settings; - } - - /** - * Set the settings value. - * - * @param settings the settings value to set - * @return the TokenRequest object itself. - */ - public TokenRequest withSettings(Map settings) { - this.settings = settings; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +/** + * A request to receive a user token. + */ +public class TokenRequest { + /** + * The provider to request a user token from. + */ + @JsonProperty(value = "provider") + private String provider; + + /** + * A collection of settings for the specific provider for this request. + */ + @JsonProperty(value = "settings") + private Map settings; + + /** + * Get the provider value. + * + * @return the provider value + */ + public String getProvider() { + return this.provider; + } + + /** + * Set the provider value. + * + * @param withProvider the provider value to set + */ + public void setProvider(String withProvider) { + this.provider = withProvider; + } + + /** + * Get the settings value. + * + * @return the settings value + */ + public Map getSettings() { + return this.settings; + } + + /** + * Set the settings value. + * + * @param withSettings the settings value to set + */ + public void setSettings(Map withSettings) { + this.settings = withSettings; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenResponse.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenResponse.java similarity index 54% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenResponse.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenResponse.java index 0c798791d..47cac46e3 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/TokenResponse.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TokenResponse.java @@ -1,121 +1,108 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A response that includes a user token. - */ -public class TokenResponse { - /** - * The channelId of the TokenResponse. - */ - @JsonProperty(value = "channelId") - private String channelId; - - /** - * The connection name. - */ - @JsonProperty(value = "connectionName") - private String connectionName; - - /** - * The user token. - */ - @JsonProperty(value = "token") - private String token; - - /** - * Expiration for the token, in ISO 8601 format (e.g. "2007-04-05T14:30Z"). - */ - @JsonProperty(value = "expiration") - private String expiration; - - /** - * Gets the channelId value. - */ - public String channelId(){ - return this.channelId; - } - - /** - * Sets the channelId value. - * - * @param channelId The channel id to set. - * @return the TokenResponse object itself. - */ - public TokenResponse withChannelId(String channelId){ - this.channelId = channelId; - return this; - } - - /** - * Get the connectionName value. - * - * @return the connectionName value - */ - public String connectionName() { - return this.connectionName; - } - - /** - * Set the connectionName value. - * - * @param connectionName the connectionName value to set - * @return the TokenResponse object itself. - */ - public TokenResponse withConnectionName(String connectionName) { - this.connectionName = connectionName; - return this; - } - - /** - * Get the token value. - * - * @return the token value - */ - public String token() { - return this.token; - } - - /** - * Set the token value. - * - * @param token the token value to set - * @return the TokenResponse object itself. - */ - public TokenResponse withToken(String token) { - this.token = token; - return this; - } - - /** - * Get the expiration value. - * - * @return the expiration value - */ - public String expiration() { - return this.expiration; - } - - /** - * Set the expiration value. - * - * @param expiration the expiration value to set - * @return the TokenResponse object itself. - */ - public TokenResponse withExpiration(String expiration) { - this.expiration = expiration; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A response that includes a user token. + */ +public class TokenResponse { + /** + * The channelId of the TokenResponse. + */ + @JsonProperty(value = "channelId") + private String channelId; + + /** + * The connection name. + */ + @JsonProperty(value = "connectionName") + private String connectionName; + + /** + * The user token. + */ + @JsonProperty(value = "token") + private String token; + + /** + * Expiration for the token, in ISO 8601 format (e.g. "2007-04-05T14:30Z"). + */ + @JsonProperty(value = "expiration") + private String expiration; + + /** + * Gets the channelId value. + */ + public String getChannelId() { + return this.channelId; + } + + /** + * Sets the channelId value. + * + * @param withChannelId The channel id to set. + */ + public void setChannelId(String withChannelId) { + this.channelId = withChannelId; + } + + /** + * Get the connectionName value. + * + * @return the connectionName value + */ + public String getConnectionName() { + return this.connectionName; + } + + /** + * Set the connectionName value. + * + * @param withConnectionName the connectionName value to set + */ + public void setConnectionName(String withConnectionName) { + this.connectionName = withConnectionName; + } + + /** + * Get the token value. + * + * @return the token value + */ + public String getToken() { + return this.token; + } + + /** + * Set the token value. + * + * @param withToken the token value to set + */ + public void setToken(String withToken) { + this.token = withToken; + } + + /** + * Get the expiration value. + * + * @return the expiration value + */ + public String getExpiration() { + return this.expiration; + } + + /** + * Set the expiration value. + * + * @param withExpiration the expiration value to set + */ + public void setExpiration(String withExpiration) { + this.expiration = withExpiration; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TraceActivity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TraceActivity.java deleted file mode 100644 index 514bf89b9..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/TraceActivity.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.microsoft.bot.schema; - -import com.microsoft.bot.schema.models.ConversationReference; - -/** - * An activity by which a bot can log internal information into a logged conversation transcript - */ -public class TraceActivity extends ActivityImpl { - /** - * Name of the trace activity - */ - private String _name; - - public String getName() { - return _name; - } - - public void setName(String name) { - _name = name; - } - - /** - * Descriptive label for the trace - */ - private String _label; - - public String getLabel() { - return _label; - } - - public void setLabel(String label) { - this._label = label; - } - - /** - * Unique string which identifies the format of the value object - */ - private String _value_type; - - public String getValueType() { - return _value_type; - } - - public void setValueType(String value_type) { - _value_type = value_type; - } - - /** - * Open-ended value - */ - private Object _value; - - Object getValue() { - return _value; - } - - void setValue(Object value) { - _value = value; - } - - /** - * Reference to another conversation or activity - */ - private ConversationReference _relates_to; - - ConversationReference getRelatesTo() { - return _relates_to; - } - - void setRelatesTo(ConversationReference relates_to) { - _relates_to = relates_to; - } -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Transcript.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Transcript.java similarity index 60% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Transcript.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Transcript.java index 405bf9917..7cc780050 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Transcript.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Transcript.java @@ -1,45 +1,40 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * A collection of Activities that conforms to the Transcript schema. - */ -public class Transcript { - /** - * List of members in this conversation. - */ - @JsonProperty(value = "activities") - private List activities; - - /** - * Gets collection of Activities that conforms to the Transcript schema. - * - * @return the activities value - */ - public List activities() { - return this.activities; - } - - /** - * Sets collection of Activities that conforms to the Transcript schema. - * - * @param activities the activities value to set - * @return the Transcript object itself. - */ - public Transcript withActivities(List activities) { - this.activities = activities; - return this; - } -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A collection of Activities that conforms to the Transcript schema. + */ +public class Transcript { + /** + * List of members in this conversation. + */ + @JsonProperty(value = "activities") + private List activities; + + /** + * Gets collection of Activities that conforms to the Transcript schema. + * + * @return the activities value + */ + public List getActivities() { + return this.activities; + } + + /** + * Sets collection of Activities that conforms to the Transcript schema. + * + * @param withActivities the activities value to set + */ + public void setActivities(List withActivities) { + this.activities = withActivities; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/VideoCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java similarity index 55% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/VideoCard.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java index c08d36491..2c8c6aa5e 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/VideoCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java @@ -1,332 +1,305 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Video card. - */ -public class VideoCard { - /** - * Title of this card. - */ - @JsonProperty(value = "title") - private String title; - - /** - * Subtitle of this card. - */ - @JsonProperty(value = "subtitle") - private String subtitle; - - /** - * Text of this card. - */ - @JsonProperty(value = "text") - private String text; - - /** - * Thumbnail placeholder. - */ - @JsonProperty(value = "image") - private ThumbnailUrl image; - - /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. - */ - @JsonProperty(value = "media") - private List media; - - /** - * Actions on this card. - */ - @JsonProperty(value = "buttons") - private List buttons; - - /** - * This content may be shared with others (default:true). - */ - @JsonProperty(value = "shareable") - private Boolean shareable; - - /** - * Should the client loop playback at end of content (default:true). - */ - @JsonProperty(value = "autoloop") - private Boolean autoloop; - - /** - * Should the client automatically start playback of media in this card - * (default:true). - */ - @JsonProperty(value = "autostart") - private Boolean autostart; - - /** - * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" - * and "4:3". - */ - @JsonProperty(value = "aspect") - private String aspect; - - /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. - */ - @JsonProperty(value = "duration") - private String duration; - - /** - * Supplementary parameter for this card. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * Get the title value. - * - * @return the title value - */ - public String title() { - return this.title; - } - - /** - * Set the title value. - * - * @param title the title value to set - * @return the VideoCard object itself. - */ - public VideoCard withTitle(String title) { - this.title = title; - return this; - } - - /** - * Get the subtitle value. - * - * @return the subtitle value - */ - public String subtitle() { - return this.subtitle; - } - - /** - * Set the subtitle value. - * - * @param subtitle the subtitle value to set - * @return the VideoCard object itself. - */ - public VideoCard withSubtitle(String subtitle) { - this.subtitle = subtitle; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the VideoCard object itself. - */ - public VideoCard withText(String text) { - this.text = text; - return this; - } - - /** - * Get the image value. - * - * @return the image value - */ - public ThumbnailUrl image() { - return this.image; - } - - /** - * Set the image value. - * - * @param image the image value to set - * @return the VideoCard object itself. - */ - public VideoCard withImage(ThumbnailUrl image) { - this.image = image; - return this; - } - - /** - * Get the media value. - * - * @return the media value - */ - public List media() { - return this.media; - } - - /** - * Set the media value. - * - * @param media the media value to set - * @return the VideoCard object itself. - */ - public VideoCard withMedia(List media) { - this.media = media; - return this; - } - - /** - * Get the buttons value. - * - * @return the buttons value - */ - public List buttons() { - return this.buttons; - } - - /** - * Set the buttons value. - * - * @param buttons the buttons value to set - * @return the VideoCard object itself. - */ - public VideoCard withButtons(List buttons) { - this.buttons = buttons; - return this; - } - - /** - * Get the shareable value. - * - * @return the shareable value - */ - public Boolean shareable() { - return this.shareable; - } - - /** - * Set the shareable value. - * - * @param shareable the shareable value to set - * @return the VideoCard object itself. - */ - public VideoCard withShareable(Boolean shareable) { - this.shareable = shareable; - return this; - } - - /** - * Get the autoloop value. - * - * @return the autoloop value - */ - public Boolean autoloop() { - return this.autoloop; - } - - /** - * Set the autoloop value. - * - * @param autoloop the autoloop value to set - * @return the VideoCard object itself. - */ - public VideoCard withAutoloop(Boolean autoloop) { - this.autoloop = autoloop; - return this; - } - - /** - * Get the autostart value. - * - * @return the autostart value - */ - public Boolean autostart() { - return this.autostart; - } - - /** - * Set the autostart value. - * - * @param autostart the autostart value to set - * @return the VideoCard object itself. - */ - public VideoCard withAutostart(Boolean autostart) { - this.autostart = autostart; - return this; - } - - /** - * Get the aspect value. - * - * @return the aspect value - */ - public String aspect() { - return this.aspect; - } - - /** - * Set the aspect value. - * - * @param aspect the aspect value to set - * @return the VideoCard object itself. - */ - public VideoCard withAspect(String aspect) { - this.aspect = aspect; - return this; - } - - /** - * Gets the duration value. - */ - public String duration(){ - return this.duration; - } - - /** - * Sets the duration value. - * - * @param duration the duration value to set - * @return the VideoCard object itself. - */ - public VideoCard withDuration(String duration){ - this.duration = duration; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the VideoCard object itself. - */ - public VideoCard withValue(Object value) { - this.value = value; - return this; - } - -} +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Video card. + */ +public class VideoCard { + /** + * Title of this card. + */ + @JsonProperty(value = "title") + private String title; + + /** + * Subtitle of this card. + */ + @JsonProperty(value = "subtitle") + private String subtitle; + + /** + * Text of this card. + */ + @JsonProperty(value = "text") + private String text; + + /** + * Thumbnail placeholder. + */ + @JsonProperty(value = "image") + private ThumbnailUrl image; + + /** + * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + */ + @JsonProperty(value = "media") + private List media; + + /** + * Actions on this card. + */ + @JsonProperty(value = "buttons") + private List buttons; + + /** + * This content may be shared with others (default:true). + */ + @JsonProperty(value = "shareable") + private boolean shareable; + + /** + * Should the client loop playback at end of content (default:true). + */ + @JsonProperty(value = "autoloop") + private boolean autoloop; + + /** + * Should the client automatically start playback of media in this card + * (default:true). + */ + @JsonProperty(value = "autostart") + private boolean autostart; + + /** + * Aspect ratio of thumbnail/media placeholder, allowed values are "16:9" + * and "4:3". + */ + @JsonProperty(value = "aspect") + private String aspect; + + /** + * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + */ + @JsonProperty(value = "duration") + private String duration; + + /** + * Supplementary parameter for this card. + */ + @JsonProperty(value = "value") + private Object value; + + /** + * Get the title value. + * + * @return the title value + */ + public String getTitle() { + return this.title; + } + + /** + * Set the title value. + * + * @param withTitle the title value to set + */ + public void setTitle(String withTitle) { + this.title = withTitle; + } + + /** + * Get the subtitle value. + * + * @return the subtitle value + */ + public String getSubtitle() { + return this.subtitle; + } + + /** + * Set the subtitle value. + * + * @param withSubtitle the subtitle value to set + */ + public void setSubtitle(String withSubtitle) { + this.subtitle = withSubtitle; + } + + /** + * Get the text value. + * + * @return the text value + */ + public String getText() { + return this.text; + } + + /** + * Set the text value. + * + * @param withText the text value to set + */ + public void setText(String withText) { + this.text = withText; + } + + /** + * Get the image value. + * + * @return the image value + */ + public ThumbnailUrl getImage() { + return this.image; + } + + /** + * Set the image value. + * + * @param withImage the image value to set + */ + public void setImage(ThumbnailUrl withImage) { + this.image = withImage; + } + + /** + * Get the media value. + * + * @return the media value + */ + public List getMedia() { + return this.media; + } + + /** + * Set the media value. + * + * @param withMedia the media value to set + */ + public void setMedia(List withMedia) { + this.media = withMedia; + } + + /** + * Get the buttons value. + * + * @return the buttons value + */ + public List getButtons() { + return this.buttons; + } + + /** + * Set the buttons value. + * + * @param withButtons the buttons value to set + */ + public void setButtons(List withButtons) { + this.buttons = withButtons; + } + + /** + * Get the shareable value. + * + * @return the shareable value + */ + public boolean getShareable() { + return this.shareable; + } + + /** + * Set the shareable value. + * + * @param withShareable the shareable value to set + */ + public void setShareable(boolean withShareable) { + this.shareable = withShareable; + } + + /** + * Get the autoloop value. + * + * @return the autoloop value + */ + public boolean getAutoloop() { + return this.autoloop; + } + + /** + * Set the autoloop value. + * + * @param withAutoloop the autoloop value to set + */ + public void setAutoloop(boolean withAutoloop) { + this.autoloop = withAutoloop; + } + + /** + * Get the autostart value. + * + * @return the autostart value + */ + public boolean getAutostart() { + return this.autostart; + } + + /** + * Set the autostart value. + * + * @param withAutostart the autostart value to set + */ + public void setAutostart(boolean withAutostart) { + this.autostart = withAutostart; + } + + /** + * Get the aspect value. + * + * @return the aspect value + */ + public String getAspect() { + return this.aspect; + } + + /** + * Set the aspect value. + * + * @param withAspect the aspect value to set + * @return the VideoCard object itself. + */ + public void setAspect(String withAspect) { + this.aspect = withAspect; + } + + /** + * Gets the duration value. + */ + public String getDuration() { + return this.duration; + } + + /** + * Sets the duration value. + * + * @param withDuration the duration value to set + */ + public void setDuration(String withDuration) { + this.duration = withDuration; + } + + /** + * Get the value value. + * + * @return the value value + */ + public Object getValue() { + return this.value; + } + + /** + * Set the value value. + * + * @param withValue the value value to set + */ + public void setValue(Object withValue) { + this.value = withValue; + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Activity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Activity.java deleted file mode 100644 index 3d479de2e..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Activity.java +++ /dev/null @@ -1,1178 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.databind.JsonNode; -import com.microsoft.bot.schema.EntityImpl; -import org.joda.time.DateTime; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An Activity is the basic communication type for the Bot Framework 3.0 - * protocol. - */ -public class Activity { - /** - * The type of the activity. Possible values include: 'message', - * 'contactRelationUpdate', 'conversationUpdate', 'typing', 'ping', - * 'endOfConversation', 'event', 'invoke', 'deleteUserData', - * 'messageUpdate', 'messageDelete', 'installationUpdate', - * 'messageReaction', 'suggestion', 'trace'. - */ - @JsonProperty(value = "type") - private ActivityTypes type; - - /** - * Contains an ID that uniquely identifies the activity on the channel. - */ - @JsonProperty(value = "id") - private String id; - - /** - * Contains the date and time that the message was sent, in UTC, expressed in ISO-8601 format. - */ - @JsonProperty(value = "timestamp") - private DateTime timestamp; - - /** - * Contains the local date and time of the message, expressed in ISO-8601 format. - * For example, 2016-09-23T13:07:49.4714686-07:00. - */ - @JsonProperty(value = "localTimestamp") - private DateTime localTimestamp; - - /** - * Contains the name of the local timezone of the message, expressed in IANA Time Zone database format. - * For example, America/Los_Angeles. - */ - @JsonProperty(value = "localTimezone") - private String localTimezone; - - /** - * A string containing an IRI identifying the caller of a bot. This field is not intended to be transmitted - * over the wire, but is instead populated by bots and clients based on cryptographically verifiable data - * that asserts the identity of the callers (e.g. tokens). - */ - @JsonProperty(value = "callerId") - private String callerId; - - /** - * Contains the URL that specifies the channel's service endpoint. Set by the channel. - */ - @JsonProperty(value = "serviceUrl") - private String serviceUrl; - - /** - * Contains an ID that uniquely identifies the channel. Set by the channel. - */ - @JsonProperty(value = "channelId") - private String channelId; - - /** - * Identifies the sender of the message. - */ - @JsonProperty(value = "from") - private ChannelAccount from; - - /** - * Identifies the conversation to which the activity belongs. - */ - @JsonProperty(value = "conversation") - private ConversationAccount conversation; - - /** - * Identifies the recipient of the message. - */ - @JsonProperty(value = "recipient") - private ChannelAccount recipient; - - /** - * Format of text fields Default:markdown. Possible values include: - * 'markdown', 'plain', 'xml'. - */ - @JsonProperty(value = "textFormat") - private TextFormatTypes textFormat; - - /** - * The layout hint for multiple attachments. Default: list. - */ - @JsonProperty(value = "attachmentLayout") - private AttachmentLayoutTypes attachmentLayout; - - /** - * The collection of members added to the conversation. - */ - @JsonProperty(value = "membersAdded") - private List membersAdded; - - /** - * The collection of members removed from the conversation. - */ - @JsonProperty(value = "membersRemoved") - private List membersRemoved; - - /** - * The collection of reactions added to the conversation. - */ - @JsonProperty(value = "reactionsAdded") - private List reactionsAdded; - - /** - * The collection of reactions removed from the conversation. - */ - @JsonProperty(value = "reactionsRemoved") - private List reactionsRemoved; - - /** - * The updated topic name of the conversation. - */ - @JsonProperty(value = "topicName") - private String topicName; - - /** - * Indicates whether the prior history of the channel is disclosed. - */ - @JsonProperty(value = "historyDisclosed") - private Boolean historyDisclosed; - - /** - * A locale name for the contents of the text field. - * The locale name is a combination of an ISO 639 two- or three-letter culture code associated with a language - * and an ISO 3166 two-letter subculture code associated with a country or region. - * - * The locale name can also correspond to a valid BCP-47 language tag. - */ - @JsonProperty(value = "locale") - private String locale; - - /** - * The text content of the message. - */ - @JsonProperty(value = "text") - private String text; - - /** - * The text to speak. - */ - @JsonProperty(value = "speak") - private String speak; - - /** - * Indicates whether your bot is accepting, expecting, or ignoring user input after the message - * is delivered to the client. - */ - @JsonProperty(value = "inputHint") - private InputHints inputHint; - - /** - * The text to display if the channel cannot render cards. - */ - @JsonProperty(value = "summary") - private String summary; - - /** - * The suggested actions for the activity. - */ - @JsonProperty(value = "suggestedActions") - private SuggestedActions suggestedActions; - - /** - * Attachments. - */ - @JsonProperty(value = "attachments") - private List attachments; - - /** - * Represents the entities that were mentioned in the message. - */ - @JsonProperty(value = "entities") - private List entities; - - /** - * Contains channel-specific content. - */ - @JsonProperty(value = "channelData") - private Object channelData; - - /** - * Indicates whether the recipient of a contactRelationUpdate was added or removed from the sender's contact list. - */ - @JsonProperty(value = "action") - private String action; - - /** - * Contains the ID of the message to which this message is a reply. - */ - @JsonProperty(value = "replyToId") - private String replyToId; - - /** - * A descriptive label for the activity. - */ - @JsonProperty(value = "label") - private String label; - - /** - * The type of the activity's value object. - */ - @JsonProperty(value = "valueType") - private String valueType; - - /** - * A value that is associated with the activity. - */ - @JsonProperty(value = "value") - private Object value; - - /** - * The name of the operation associated with an invoke or event activity. - */ - @JsonProperty(value = "name") - private String name; - - /** - * A reference to another conversation or activity. - */ - @JsonProperty(value = "relatesTo") - private ConversationReference relatesTo; - - /** - * The a code for endOfConversation activities that indicates why the conversation ended. - */ - @JsonProperty(value = "code") - private EndOfConversationCodes code; - - /** - * The time at which the activity should be considered to be expired and should not be presented to the recipient. - */ - @JsonProperty(value = "expiration") - private DateTime expiration; - - /** - * The importance of the activity. - */ - @JsonProperty(value = "importance") - private String importance; - - /** - * A delivery hint to signal to the recipient alternate delivery paths for the activity. - * - * The default delivery mode is \"default\". - */ - @JsonProperty(value = "deliveryMode") - private String deliveryMode; - - /** - * List of phrases and references that speech and language priming systems should listen for. - */ - @JsonProperty(value = "listenFor") - private List listenFor; - - /** - * The collection of text fragments to highlight when the activity contains a ReplyToId value. - */ - @JsonProperty(value = "textHighlights") - private List textHighlights; - - /** - * Get the type value. - * - * @return the type value - */ - public ActivityTypes type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Activity object itself. - */ - public Activity withType(ActivityTypes type) { - this.type = type; - return this; - } - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the Activity object itself. - */ - public Activity withId(String id) { - this.id = id; - return this; - } - - /** - * Get the timestamp value. - * - * @return the timestamp value - */ - public DateTime timestamp() { - return this.timestamp; - } - - /** - * Set the timestamp value. - * - * @param timestamp the timestamp value to set - * @return the Activity object itself. - */ - public Activity withTimestamp(DateTime timestamp) { - this.timestamp = timestamp; - return this; - } - - /** - * Get the localTimestamp value. - * - * @return the localTimestamp value - */ - public DateTime localTimestamp() { - return this.localTimestamp; - } - - /** - * Set the localTimestamp value. - * - * @param localTimestamp the localTimestamp value to set - * @return the Activity object itself. - */ - public Activity withLocalTimestamp(DateTime localTimestamp) { - this.localTimestamp = localTimestamp; - return this; - } - - /** - * Gets the localTimezone. - * - * @return The name of the local timezone of the message, expressed in IANA Time Zone database format. - */ - public String localTimezone(){ - return this.localTimezone; - } - - /** - * Sets the localTimezone. - * @param localTimezone The name of the local timezone of the message, expressed in IANA Time Zone database format. - */ - public Activity withLocalTimeZone(String localTimezone){ - this.localTimezone = localTimezone; - return this; - } - - /** - * Gets the callerId - */ - public String callerId(){ - return this.callerId; - } - - /** - * Sets the callerId - * - * @param callerId A string containing an IRI identifying the caller of a bot. - */ - public Activity withCallerId(String callerId){ - this.callerId = callerId; - return this; - } - - /** - * Get the serviceUrl value. - * - * @return the serviceUrl value - */ - public String serviceUrl() { - return this.serviceUrl; - } - - /** - * Set the serviceUrl value. - * - * @param serviceUrl the serviceUrl value to set - * @return the Activity object itself. - */ - public Activity withServiceUrl(String serviceUrl) { - this.serviceUrl = serviceUrl; - return this; - } - - /** - * Get the channelId value. - * - * @return the channelId value - */ - public String channelId() { - return this.channelId; - } - - /** - * Set the channelId value. - * - * @param channelId the channelId value to set - * @return the Activity object itself. - */ - public Activity withChannelId(String channelId) { - this.channelId = channelId; - return this; - } - - /** - * Get the from value. - * - * @return the from value - */ - public ChannelAccount from() { - return this.from; - } - - /** - * Set the from value. - * - * @param from the from value to set - * @return the Activity object itself. - */ - public Activity withFrom(ChannelAccount from) { - this.from = from; - return this; - } - - /** - * Get the conversation value. - * - * @return the conversation value - */ - public ConversationAccount conversation() { - return this.conversation; - } - - /** - * Set the conversation value. - * - * @param conversation the conversation value to set - * @return the Activity object itself. - */ - public Activity withConversation(ConversationAccount conversation) { - this.conversation = conversation; - return this; - } - - /** - * Get the recipient value. - * - * @return the recipient value - */ - public ChannelAccount recipient() { - return this.recipient; - } - - /** - * Set the recipient value. - * - * @param recipient the recipient value to set - * @return the Activity object itself. - */ - public Activity withRecipient(ChannelAccount recipient) { - this.recipient = recipient; - return this; - } - - /** - * Get the textFormat value. - * - * @return the textFormat value - */ - public TextFormatTypes textFormat() { - return this.textFormat; - } - - /** - * Set the textFormat value. - * - * @param textFormat the textFormat value to set - * @return the Activity object itself. - */ - public Activity withTextFormat(TextFormatTypes textFormat) { - this.textFormat = textFormat; - return this; - } - - /** - * Get the attachmentLayout value. - * - * @return the attachmentLayout value - */ - public AttachmentLayoutTypes attachmentLayout() { - return this.attachmentLayout; - } - - /** - * Set the attachmentLayout value. - * - * @param attachmentLayout the attachmentLayout value to set - * @return the Activity object itself. - */ - public Activity withAttachmentLayout(AttachmentLayoutTypes attachmentLayout) { - this.attachmentLayout = attachmentLayout; - return this; - } - - /** - * Get the membersAdded value. - * - * @return the membersAdded value - */ - public List membersAdded() { - return this.membersAdded; - } - - /** - * Set the membersAdded value. - * - * @param membersAdded the membersAdded value to set - * @return the Activity object itself. - */ - public Activity withMembersAdded(List membersAdded) { - this.membersAdded = membersAdded; - return this; - } - - /** - * Get the membersRemoved value. - * - * @return the membersRemoved value - */ - public List membersRemoved() { - return this.membersRemoved; - } - - /** - * Set the membersRemoved value. - * - * @param membersRemoved the membersRemoved value to set - * @return the Activity object itself. - */ - public Activity withMembersRemoved(List membersRemoved) { - this.membersRemoved = membersRemoved; - return this; - } - - /** - * Get the reactionsAdded value. - * - * @return the reactionsAdded value - */ - public List reactionsAdded() { - return this.reactionsAdded; - } - - /** - * Set the reactionsAdded value. - * - * @param reactionsAdded the reactionsAdded value to set - * @return the Activity object itself. - */ - public Activity withReactionsAdded(List reactionsAdded) { - this.reactionsAdded = reactionsAdded; - return this; - } - - /** - * Get the reactionsRemoved value. - * - * @return the reactionsRemoved value - */ - public List reactionsRemoved() { - return this.reactionsRemoved; - } - - /** - * Set the reactionsRemoved value. - * - * @param reactionsRemoved the reactionsRemoved value to set - * @return the Activity object itself. - */ - public Activity withReactionsRemoved(List reactionsRemoved) { - this.reactionsRemoved = reactionsRemoved; - return this; - } - - /** - * Get the topicName value. - * - * @return the topicName value - */ - public String topicName() { - return this.topicName; - } - - /** - * Set the topicName value. - * - * @param topicName the topicName value to set - * @return the Activity object itself. - */ - public Activity withTopicName(String topicName) { - this.topicName = topicName; - return this; - } - - /** - * Get the historyDisclosed value. - * - * @return the historyDisclosed value - */ - public Boolean historyDisclosed() { - return this.historyDisclosed; - } - - /** - * Set the historyDisclosed value. - * - * @param historyDisclosed the historyDisclosed value to set - * @return the Activity object itself. - */ - public Activity withHistoryDisclosed(Boolean historyDisclosed) { - this.historyDisclosed = historyDisclosed; - return this; - } - - /** - * Get the locale value. - * - * @return the locale value - */ - public String locale() { - return this.locale; - } - - /** - * Set the locale value. - * - * @param locale the locale value to set - * @return the Activity object itself. - */ - public Activity withLocale(String locale) { - this.locale = locale; - return this; - } - - /** - * Get the text value. - * - * @return the text value - */ - public String text() { - return this.text; - } - - /** - * Set the text value. - * - * @param text the text value to set - * @return the Activity object itself. - */ - public Activity withText(String text) { - this.text = text; - return this; - } - - /** - * Get the speak value. - * - * @return the speak value - */ - public String speak() { - return this.speak; - } - - /** - * Set the speak value. - * - * @param speak the speak value to set - * @return the Activity object itself. - */ - public Activity withSpeak(String speak) { - this.speak = speak; - return this; - } - - /** - * Get the inputHint value. - * - * @return the inputHint value - */ - public InputHints inputHint() { - return this.inputHint; - } - - /** - * Set the inputHint value. - * - * @param inputHint the inputHint value to set - * @return the Activity object itself. - */ - public Activity withInputHint(InputHints inputHint) { - this.inputHint = inputHint; - return this; - } - - /** - * Get the summary value. - * - * @return the summary value - */ - public String summary() { - return this.summary; - } - - /** - * Set the summary value. - * - * @param summary the summary value to set - * @return the Activity object itself. - */ - public Activity withSummary(String summary) { - this.summary = summary; - return this; - } - - /** - * Get the suggestedActions value. - * - * @return the suggestedActions value - */ - public SuggestedActions suggestedActions() { - return this.suggestedActions; - } - - /** - * Set the suggestedActions value. - * - * @param suggestedActions the suggestedActions value to set - * @return the Activity object itself. - */ - public Activity withSuggestedActions(SuggestedActions suggestedActions) { - this.suggestedActions = suggestedActions; - return this; - } - - /** - * Get the attachments value. - * - * @return the attachments value - */ - public List attachments() { - return this.attachments; - } - - /** - * Set the attachments value. - * - * @param attachments the attachments value to set - * @return the Activity object itself. - */ - public Activity withAttachments(List attachments) { - this.attachments = attachments; - return this; - } - - /** - * Get the entities value. - * - * @return the entities value - */ - public List entities() { - return this.entities; - } - - /** - * Set the entities value. - * - * @param entities the entities value to set - * @return the Activity object itself. - */ - public Activity withEntities(List entities) { - this.entities = entities; - return this; - } - - /** - * Get the channelData value. - * - * @return the channelData value - */ - public Object channelData() { - return this.channelData; - } - - /** - * Set the channelData value. - * - * @param channelData the channelData value to set - * @return the Activity object itself. - */ - public Activity withChannelData(Object channelData) { - this.channelData = channelData; - return this; - } - - /** - * Get the action value. - * - * @return the action value - */ - public String action() { - return this.action; - } - - /** - * Set the action value. - * - * @param action the action value to set - * @return the Activity object itself. - */ - public Activity withAction(String action) { - this.action = action; - return this; - } - - /** - * Get the replyToId value. - * - * @return the replyToId value - */ - public String replyToId() { - return this.replyToId; - } - - /** - * Set the replyToId value. - * - * @param replyToId the replyToId value to set - * @return the Activity object itself. - */ - public Activity withReplyToId(String replyToId) { - this.replyToId = replyToId; - return this; - } - - /** - * Get the label value. - * - * @return the label value - */ - public String label() { - return this.label; - } - - /** - * Set the label value. - * - * @param label the label value to set - * @return the Activity object itself. - */ - public Activity withLabel(String label) { - this.label = label; - return this; - } - - /** - * Get the valueType value. - * - * @return the valueType value - */ - public String valueType() { - return this.valueType; - } - - /** - * Set the valueType value. - * - * @param valueType the valueType value to set - * @return the Activity object itself. - */ - public Activity withValueType(String valueType) { - this.valueType = valueType; - return this; - } - - /** - * Get the value value. - * - * @return the value value - */ - public Object value() { - return this.value; - } - - /** - * Set the value value. - * - * @param value the value value to set - * @return the Activity object itself. - */ - public Activity withValue(Object value) { - this.value = value; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the Activity object itself. - */ - public Activity withName(String name) { - this.name = name; - return this; - } - - /** - * Get the relatesTo value. - * - * @return the relatesTo value - */ - public ConversationReference relatesTo() { - return this.relatesTo; - } - - /** - * Set the relatesTo value. - * - * @param relatesTo the relatesTo value to set - * @return the Activity object itself. - */ - public Activity withRelatesTo(ConversationReference relatesTo) { - this.relatesTo = relatesTo; - return this; - } - - /** - * Get the code value. - * - * @return the code value - */ - public EndOfConversationCodes code() { - return this.code; - } - - /** - * Set the code value. - * - * @param code the code value to set - * @return the Activity object itself. - */ - public Activity withCode(EndOfConversationCodes code) { - this.code = code; - return this; - } - - /** - * Get the expiration value. - * - * @return the expiration value - */ - public DateTime expiration() { - return this.expiration; - } - - /** - * Set the expiration value. - * - * @param expiration the expiration value to set - * @return the Activity object itself. - */ - public Activity withExpiration(DateTime expiration) { - this.expiration = expiration; - return this; - } - - /** - * Get the importance value. - * - * @return the importance value - */ - public String importance() { - return this.importance; - } - - /** - * Set the importance value. - * - * @param importance the importance value to set - * @return the Activity object itself. - */ - public Activity withImportance(String importance) { - this.importance = importance; - return this; - } - - /** - * Get the deliveryMode value. - * - * @return the deliveryMode value - */ - public String deliveryMode() { - return this.deliveryMode; - } - - /** - * Set the deliveryMode value. - * - * @param deliveryMode the deliveryMode value to set - * @return the Activity object itself. - */ - public Activity withDeliveryMode(String deliveryMode) { - this.deliveryMode = deliveryMode; - return this; - } - - /** - * Gets listenFor value. - */ - public List listenFor(){ - return this.listenFor; - } - - /** - * Sets listenFor value on this object. - */ - public Activity withListenFor(List listenFor){ - this.listenFor = listenFor; - return this; - } - - /** - * Get the textHighlights value. - * - * @return the textHighlights value - */ - public List textHighlights() { - return this.textHighlights; - } - - /** - * Set the textHighlights value. - * - * @param textHighlights the textHighlights value to set - * @return the Activity object itself. - */ - public Activity withTextHighlights(List textHighlights) { - this.textHighlights = textHighlights; - return this; - } - /** - * Holds the overflow properties that aren't first class - * properties in the object. This allows extensibility - * while maintaining the object. - * - */ - private HashMap properties = new HashMap(); - - /** - * Overflow properties. - * Properties that are not modelled as first class properties in the object are accessible here. - * Note: A property value can be be nested. - * - * @return A Key-Value map of the properties - */ - @JsonAnyGetter - public Map properties() { - return this.properties; - } - - /** - * Set overflow properties. - * - * @param key Key for the property - * @param value JsonNode of value (can be nested) - * - */ - - @JsonAnySetter - public void setProperties(String key, JsonNode value) { - this.properties.put(key, value); - } - - /** - Updates this activity with the delivery information from an existing - conversation reference. - - @param reference The conversation reference. - @param isIncoming (Optional) true to treat the activity as an - incoming activity, where the bot is the recipient; otherwaire false. - Default is false, and the activity will show the bot as the sender. - Call on an incoming - activity to get a conversation reference that you can then use to update an - outgoing activity with the correct delivery information. - - */ - - - public final Activity applyConversationReference(ConversationReference reference) - { - return applyConversationReference(reference, false); - } - - public final Activity applyConversationReference(ConversationReference reference, boolean isIncoming) - { - this.withChannelId(reference.channelId()); - this.withServiceUrl(reference.serviceUrl()); - this.withConversation(reference.conversation()); - - if (isIncoming) - { - this.withFrom(reference.user()); - this.withRecipient(reference.bot()); - if (reference.activityId() != null) - { - this.withId(reference.activityId()); - } - } - else // Outgoing - { - this.withFrom(reference.bot()); - this.withRecipient(reference.user()); - if (reference.activityId() != null) - { - this.withReplyToId(reference.activityId()); - } - } - return this; - } - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ChannelAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ChannelAccount.java deleted file mode 100644 index e2584f475..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ChannelAccount.java +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; - -import java.util.HashMap; -import java.util.Map; - -/** - * Channel account information needed to route a message. - */ -public class ChannelAccount { - /** - * Channel id for the user or bot on this channel (Example: joe@smith.com, - * or @joesmith or 123456). - */ - @JsonProperty(value = "id") - private String id; - - /** - * Display friendly name. - */ - @JsonProperty(value = "name") - private String name; - - /** - * This account's object ID within Azure Active Directory (AAD) - */ - @JsonProperty(value = "aadObjectId") - private String aadObjectId; - - /** - * Role of the entity behind the account (Example: User, Bot, etc.). - * Possible values include: 'user', 'bot'. - */ - @JsonProperty(value = "role") - private RoleTypes role; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the ChannelAccount object itself. - */ - public ChannelAccount withId(String id) { - this.id = id; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the ChannelAccount object itself. - */ - public ChannelAccount withName(String name) { - this.name = name; - return this; - } - - /** - * Get the role value. - * - * @return the role value - */ - public RoleTypes role() { - return this.role; - } - - /** - * Set the role value. - * - * @param role the role value to set - * @return the ChannelAccount object itself. - */ - public ChannelAccount withRole(RoleTypes role) { - this.role = role; - return this; - } - - - /** - * Holds the overflow properties that aren't first class - * properties in the object. This allows extensibility - * while maintaining the object. - * - */ - private HashMap properties = new HashMap(); - - /** - * Overflow properties. - * Properties that are not modelled as first class properties in the object are accessible here. - * Note: A property value can be be nested. - * - * @return A Key-Value map of the properties - */ - @JsonAnyGetter - public Map properties() { - return this.properties; - } - - /** - * Set overflow properties. - * - * @param key Key for the property - * @param value JsonNode of value (can be nested) - * - */ - - @JsonAnySetter - public void setProperties(String key, JsonNode value) { - this.properties.put(key, value); - } - - /** - * Gets aadObjectId - */ - public String aadObjectId(){ - return this.aadObjectId; - } - - /** - * Sets aadObjectId - */ - public ChannelAccount withAadObjectId(String aadObjectId){ - this.aadObjectId = aadObjectId; - return this; - } -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationAccount.java deleted file mode 100644 index 83b17e9c0..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationAccount.java +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Conversation account represents the identity of the conversation within a channel. - */ -public class ConversationAccount { - /** - * Indicates whether the conversation contains more than two participants - * at the time the activity was generated. - */ - @JsonProperty(value = "isGroup") - private Boolean isGroup; - - /** - * Indicates the type of the conversation in channels that distinguish - * between conversation types. - */ - @JsonProperty(value = "conversationType") - private String conversationType; - - /** - * This conversation's tenant ID. - */ - @JsonProperty(value = "tenantId") - private String tenantId; - - /** - * Channel id for the user or bot on this channel (Example: joe@smith.com, - * or @joesmith or 123456). - */ - @JsonProperty(value = "id") - private String id; - - /** - * Display friendly name. - */ - @JsonProperty(value = "name") - private String name; - - /** - * This account's object ID within Azure Active Directory (AAD). - */ - @JsonProperty(value = "aadObjectId") - private String aadObjectId; - - /** - * Role of the entity behind the account (Example: User, Bot, etc.). - * Possible values include: 'user', 'bot'. - */ - @JsonProperty(value = "role") - private RoleTypes role; - - /** - * Get the isGroup value. - * - * @return the isGroup value - */ - public Boolean isGroup() { - return this.isGroup; - } - - /** - * Set the isGroup value. - * - * @param isGroup the isGroup value to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withIsGroup(Boolean isGroup) { - this.isGroup = isGroup; - return this; - } - - /** - * Get the conversationType value. - * - * @return the conversationType value - */ - public String conversationType() { - return this.conversationType; - } - - /** - * Set the conversationType value. - * - * @param conversationType the conversationType value to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withConversationType(String conversationType) { - this.conversationType = conversationType; - return this; - } - - /** - * Gets this conversation's tenant ID. - */ - public String tenantId(){ - return this.tenantId; - } - - /** - * Sets this conversation's tenant ID. - * - * @param tenantId this conversation's tenant ID - * @return the ConversationAccount object itself. - */ - public ConversationAccount withTenantId(String tenantId){ - this.tenantId = tenantId; - return this; - } - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withId(String id) { - this.id = id; - return this; - } - - /** - * Get the name value. - * - * @return the name value - */ - public String name() { - return this.name; - } - - /** - * Set the name value. - * - * @param name the name value to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withName(String name) { - this.name = name; - return this; - } - - /** - * Gets this account's object ID within Azure Active Directory (AAD). - */ - public String aadObjectId(){ - return this.aadObjectId; - } - - /** - * Sets this account's object ID within Azure Active Directory (AAD). - - * @param name the AAD ID to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withAadObjectId(String aadObjectId){ - this.aadObjectId = aadObjectId; - return this; - } - - /** - * Get the role value. - * - * @return the role value - */ - public RoleTypes role() { - return this.role; - } - - /** - * Set the role value. - * - * @param role the role value to set - * @return the ConversationAccount object itself. - */ - public ConversationAccount withRole(RoleTypes role) { - this.role = role; - return this; - } - /** - * Holds the overflow properties that aren't first class - * properties in the object. This allows extensibility - * while maintaining the object. - * - */ -// private HashMap properties = new HashMap(); - - /** - * Overflow properties. - * Properties that are not modelled as first class properties in the object are accessible here. - * Note: A property value can be be nested. - * - * @return A Key-Value map of the properties - */ -// @JsonAnyGetter -// public Map properties() { -// return this.properties; -// } - - /** - * Set overflow properties. - * - * @param key Key for the property - * @param value JsonNode of value (can be nested) - * - */ - -// @JsonAnySetter -// public void setProperties(String key, JsonNode value) { -// this.properties.put(key, value); -// } - - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationMembers.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationMembers.java deleted file mode 100644 index a6b2d21de..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationMembers.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Conversation and its members. - */ -public class ConversationMembers { - /** - * Conversation ID. - */ - @JsonProperty(value = "id") - private String id; - - /** - * List of members in this conversation. - */ - @JsonProperty(value = "members") - private List members; - - /** - * Get the id value. - * - * @return the id value - */ - public String id() { - return this.id; - } - - /** - * Set the id value. - * - * @param id the id value to set - * @return the ConversationMembers object itself. - */ - public ConversationMembers withId(String id) { - this.id = id; - return this; - } - - /** - * Get the members value. - * - * @return the members value - */ - public List members() { - return this.members; - } - - /** - * Set the members value. - * - * @param members the members value to set - * @return the ConversationMembers object itself. - */ - public ConversationMembers withMembers(List members) { - this.members = members; - return this; - } - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationParameters.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationParameters.java deleted file mode 100644 index 9cd544465..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationParameters.java +++ /dev/null @@ -1,197 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import java.util.List; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Parameters for creating a new conversation. - */ -public class ConversationParameters { - /** - * IsGroup. - */ - @JsonProperty(value = "isGroup") - private Boolean isGroup; - - /** - * The bot address for this conversation. - */ - @JsonProperty(value = "bot") - private ChannelAccount bot; - - /** - * Members to add to the conversation. - */ - @JsonProperty(value = "members") - private List members; - - /** - * (Optional) Topic of the conversation (if supported by the channel). - */ - @JsonProperty(value = "topicName") - private String topicName; - - /** - * (Optional) The tenant ID in which the conversation should be created. - */ - @JsonProperty(value = "tenantId") - private String tenantId; - - /** - * (Optional) When creating a new conversation, use this activity as the - * intial message to the conversation. - */ - @JsonProperty(value = "activity") - private Activity activity; - - /** - * Channel specific payload for creating the conversation. - */ - @JsonProperty(value = "channelData") - private Object channelData; - - /** - * Get the isGroup value. - * - * @return the isGroup value - */ - public Boolean isGroup() { - return this.isGroup; - } - - /** - * Set the isGroup value. - * - * @param isGroup the isGroup value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withIsGroup(Boolean isGroup) { - this.isGroup = isGroup; - return this; - } - - /** - * Get the bot value. - * - * @return the bot value - */ - public ChannelAccount bot() { - return this.bot; - } - - /** - * Set the bot value. - * - * @param bot the bot value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withBot(ChannelAccount bot) { - this.bot = bot; - return this; - } - - /** - * Get the members value. - * - * @return the members value - */ - public List members() { - return this.members; - } - - /** - * Set the members value. - * - * @param members the members value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withMembers(List members) { - this.members = members; - return this; - } - - /** - * Get the topicName value. - * - * @return the topicName value - */ - public String topicName() { - return this.topicName; - } - - /** - * Set the topicName value. - * - * @param topicName the topicName value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withTopicName(String topicName) { - this.topicName = topicName; - return this; - } - - /** - * Get the activity value. - * - * @return the activity value - */ - public Activity activity() { - return this.activity; - } - - /** - * Set the activity value. - * - * @param activity the activity value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withActivity(Activity activity) { - this.activity = activity; - return this; - } - - /** - * Get the channelData value. - * - * @return the channelData value - */ - public Object channelData() { - return this.channelData; - } - - /** - * Set the channelData value. - * - * @param channelData the channelData value to set - * @return the ConversationParameters object itself. - */ - public ConversationParameters withChannelData(Object channelData) { - this.channelData = channelData; - return this; - } - - /** - * Gets tenantId - */ - public String tenantId(){ - return this.tenantId; - } - - /** - * Sets tenantId - */ - public ConversationParameters withTenantId(String tenantId){ - this.tenantId = tenantId; - return this; - } -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReferenceHelper.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReferenceHelper.java deleted file mode 100644 index 8a8b83a60..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationReferenceHelper.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.microsoft.bot.schema.models; - -import com.microsoft.bot.schema.ActivityImpl; - -import java.util.UUID; - -public class ConversationReferenceHelper { - private ConversationReference reference; - public ConversationReferenceHelper(ConversationReference reference) { - this.reference = reference; - } - /** - * Creates {@link Activity} from conversation reference as it is posted to bot. - */ - public ActivityImpl GetPostToBotMessage() - { - return (ActivityImpl) new ActivityImpl() - .withType(ActivityTypes.MESSAGE) - .withId(UUID.randomUUID().toString()) - .withRecipient(new ChannelAccount() - .withId(reference.bot().id()) - .withName(reference.bot().name())) - .withChannelId(reference.channelId()) - .withServiceUrl(reference.serviceUrl()) - .withConversation(new ConversationAccount() - .withId(reference.conversation().id()) - .withIsGroup(reference.conversation().isGroup()) - .withName(reference.conversation().name())) - .withFrom(new ChannelAccount() - .withId(reference.user().id()) - .withName(reference.user().name())); - } - - /** - * Creates {@link Activity} from conversation reference that can be posted to user as reply. - */ - public ActivityImpl GetPostToUserMessage() - { - Activity msg = this.GetPostToBotMessage(); - - // swap from and recipient - ChannelAccount bot = msg.recipient(); - ChannelAccount user = msg.from(); - msg.withFrom(bot); - msg.withRecipient(user); - return (ActivityImpl) msg; - } -} - - diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationUpdateActivity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationUpdateActivity.java deleted file mode 100644 index 9c8578a5c..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/ConversationUpdateActivity.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.microsoft.bot.schema.models; - -// Note: In C# implementation, main Activity interface does not contain complete wire format. - -import java.util.List; - -public class ConversationUpdateActivity extends MessageActivity { - /** - * Members added to the conversation - */ - private List membersAdded; - - @Override - public List membersAdded() { - return this.membersAdded; - } - @Override - public ConversationUpdateActivity withMembersAdded(List membersAdded) { - this.membersAdded = membersAdded; - return this; - } - - /** - * Members removed from the conversation - */ - private List membersRemoved; - public List membersRemoved() { - return this.membersRemoved; - } - @Override - public ConversationUpdateActivity withMembersRemoved(List membersRemoved) { - - this.membersRemoved = membersRemoved; - return this; - } - - /** - * The conversation's updated topic name - */ - private String topicName; - @Override - public String topicName() { - return this.topicName; - } - @Override - public ConversationUpdateActivity withTopicName(String topicname) { - this.topicName = topicname; - return this; - } - - - /** - * True if prior history of the channel is disclosed - * Note: Boolean (class) is used, may be null - */ - private Boolean historyDisclosed; - public Boolean historyDisclosed() { - return this.historyDisclosed; - } - public ConversationUpdateActivity withHistoryDisclosed(Boolean historydisclosed) { - this.historyDisclosed = historydisclosed; - return this; - } -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Entity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Entity.java deleted file mode 100644 index e24c08022..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/Entity.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for - * license information. - * - * Code generated by Microsoft (R) AutoRest Code Generator. - * Changes may cause incorrect behavior and will be lost if the code is - * regenerated. - */ - -package com.microsoft.bot.schema.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Metadata object pertaining to an activity - */ -public class Entity { - /** - * Type of this entity (RFC 3987 IRI). - */ - @JsonProperty(value = "type") - private String type; - - /** - * Get the type value. - * - * @return the type value - */ - public String type() { - return this.type; - } - - /** - * Set the type value. - * - * @param type the type value to set - * @return the Entity object itself. - */ - public Entity withType(String type) { - this.type = type; - return this; - } - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageActivity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageActivity.java deleted file mode 100644 index 6e39c21eb..000000000 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/MessageActivity.java +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -package com.microsoft.bot.schema.models; - -import com.microsoft.bot.schema.ActivityImpl; - -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.List; - - /** - * A message in a conversation - */ -public class MessageActivity extends ActivityImpl -{ - /** - * The language code of the Text field - */ - private String locale; - public String getLocale() { - return this.locale; - } - public void setLocale(String locale) { - this.locale = locale; - - } - - /** - * Content for the message - */ - private String text; - public void setText(String text){ - this.text = text; - } - public String getText() { - - return this.text; - } - - /** - * Speak tag (SSML markup for text to speech) - */ - private String speak; - public void setSpeak(String speak){ - this.speak = speak; - } - public String getSpeak(){ - return this.speak; - } - - /** - * Indicates whether the bot is accepting, expecting, or ignoring input - */ - private String inputHint; - public String getInputHint(){ - return this.inputHint; - } - public void setInputHint(String inputHint){ - this.inputHint = inputHint; - } - - /** - * Text to display if the channel cannot render cards - */ - private String summary; - public String getSummary(){ - return this.summary; - } - public void setSummary(String summary) { - this.summary = summary; - } - - /** - * Format of text fields [plain|markdown] Default:markdown - */ - private String textFormat; - public String getTextFormat() { - - return this.textFormat; - } - public void setTextFormat(String textFormat) { - this.textFormat = textFormat; - } - - /** - * Hint for how to deal with multiple attachments: [list|carousel] Default:list - */ - private String attachmentLayout; - public String getAttachmentLayout() { - return this.attachmentLayout; - } - public void setAttachmentLayout(String attachmentLayout) { - this.attachmentLayout = attachmentLayout; - } - - /** - * Attachments - */ - private List attachments; - public List getAttachments() { - return this.attachments; - } - public void setAttachments(List attachments) { - this.attachments = attachments; - } - - /** - * SuggestedActions are used to express actions for interacting with a card like keyboards/quickReplies - */ - private SuggestedActions suggestedActions; - public SuggestedActions getSuggestedActions() { - return this.suggestedActions; - } - public void setSuggestedActions(SuggestedActions suggestedActions) { - this.suggestedActions = suggestedActions; - } - - - /** - * Importance of the activity - * Valid values are "low", "normal", and "high". Default value is "normal." - */ - private String importance; - public String getImportance() { - return this.importance; - } - public void setImportance(String importance) { - this.importance = importance; - } - - /** - * Hint to describe how this activity should be delivered. - * null or "default" = default delivery - * "notification" = notification semantics - * See DeliveryModes for current constants - */ - private String deliveryMode; - public String getDeliveryMode() { - return this.deliveryMode; - } - public void setDeliveryMode(String deliveryMode) { - this.deliveryMode = deliveryMode; - } - - /** - * DateTime to expire the activity as ISO 8601 encoded datetime - */ - private OffsetDateTime expiration; - public OffsetDateTime getExpiration() { - return this.expiration; - } - public void setExpiration(OffsetDateTime expiration) { - this.expiration = expiration; - } - - /** - * Get mentions - */ - private ArrayList mentions; - public ArrayList GetMentions() { - return this.mentions; - } - - /** - * Value provided with CardAction - */ - private Object value; - public Object getValue() { - return this.value; - } - public void setValue(Object value) { - this.value = value; - } - - - /** - * Create an instance of the Activity class with IConversationUpdateActivity masking - */ - public static ConversationUpdateActivity CreateConversationUpdateActivity() - { - ConversationUpdateActivity conversationActivity = new ConversationUpdateActivity(); - conversationActivity.withType(ActivityTypes.CONVERSATION_UPDATE); - conversationActivity.withMembersAdded(new ArrayList()); - conversationActivity.withMembersRemoved(new ArrayList()); - return conversationActivity; - } - -} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/package-info.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/package-info.java similarity index 50% rename from libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/package-info.java rename to libraries/bot-schema/src/main/java/com/microsoft/bot/schema/package-info.java index 50c92b17c..3468cb598 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/models/package-info.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/package-info.java @@ -1,25 +1,25 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for -// license information. -// -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is -// regenerated. - -/** - * This package contains the models classes for ConnectorClient. - * The Bot Connector REST API allows your bot to send and receive messages to channels configured in the - [Bot Framework Developer Portal](https://dev.botframework.com). The Connector service uses industry-standard REST - and JSON over HTTPS. - Client libraries for this REST API are available. See below for a list. - Many bots will use both the Bot Connector REST API and the associated [Bot State REST API](/en-us/restapi/state). The - Bot State REST API allows a bot to store and retrieve state associated with users and conversations. - Authentication for both the Bot Connector and Bot State REST APIs is accomplished with JWT Bearer tokens, and is - described in detail in the [Connector Authentication](/en-us/restapi/authentication) document. - # Client Libraries for the Bot Connector REST API - * [Bot Builder for C#](/en-us/csharp/builder/sdkreference/) - * [Bot Builder for Node.js](/en-us/node/builder/overview/) - * Generate your own from the [Connector API Swagger file](https://raw.githubusercontent.com/Microsoft/BotBuilder/master/CSharp/Library/Microsoft.Bot.Connector.Shared/Swagger/ConnectorAPI.json) - © 2016 Microsoft. - */ -package com.microsoft.bot.schema.models; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. + +/** + * This package contains the models classes for ConnectorClient. + * The Bot Connector REST API allows your bot to send and receive messages to channels configured in the + * [Bot Framework Developer Portal](https://dev.botframework.com). The Connector service uses industry-standard REST + * and JSON over HTTPS. + * Client libraries for this REST API are available. See below for a list. + * Many bots will use both the Bot Connector REST API and the associated [Bot State REST API](/en-us/restapi/state). The + * Bot State REST API allows a bot to store and retrieve state associated with users and conversations. + * Authentication for both the Bot Connector and Bot State REST APIs is accomplished with JWT Bearer tokens, and is + * described in detail in the [Connector Authentication](/en-us/restapi/authentication) document. + * # Client Libraries for the Bot Connector REST API + * [Bot Builder for C#](/en-us/csharp/builder/sdkreference/) + * [Bot Builder for Node.js](/en-us/node/builder/overview/) + * Generate your own from the [Connector API Swagger file](https://raw.githubusercontent.com/Microsoft/BotBuilder/master/CSharp/Library/Microsoft.Bot.Connector.Shared/Swagger/ConnectorAPI.json) + * © 2016 Microsoft. + */ +package com.microsoft.bot.schema; diff --git a/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java new file mode 100644 index 000000000..c440939ca --- /dev/null +++ b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java @@ -0,0 +1,21 @@ +package com.microsoft.bot.schema; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.Test; + +public class ActivityTest { + @Test + public void GetConversationReference() { + + } + + private Activity createActivity() { + ChannelAccount account1 = new ChannelAccount() {{ + setId("ChannelAccount_Id_1"); + setName("ChannelAccount_Name_1"); + setProperties("Name", JsonNodeFactory.instance.objectNode()); + + }}; + } +} diff --git a/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/EntitySchemaValidationTest.java b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/EntitySchemaValidationTest.java new file mode 100644 index 000000000..90f69e707 --- /dev/null +++ b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/EntitySchemaValidationTest.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.schema; + +import org.junit.Assert; +import org.junit.Test; + +public class EntitySchemaValidationTest { + @Test + public void EntityTests_GeoCoordinatesSerializationDeserializationTest() { + GeoCoordinates geoCoordinates = new GeoCoordinates() {{ + setLatitude(22.00); + setLongitude(23.00); + }}; + + Assert.assertEquals("GeoCoordinates", geoCoordinates.getType()); + + Entity deserializedEntity = new Entity().setAs(geoCoordinates); + Assert.assertEquals(deserializedEntity.getType(), geoCoordinates.getType()); + + GeoCoordinates geoDeserialized = deserializedEntity.getAs(GeoCoordinates.class); + Assert.assertEquals(geoCoordinates.getType(), geoDeserialized.getType()); + Assert.assertEquals(geoCoordinates.getLatitude(), geoDeserialized.getLatitude(), Double.MAX_VALUE); + Assert.assertEquals(geoCoordinates.getLongitude(), geoDeserialized.getLongitude(), Double.MAX_VALUE); + } + + @Test + public void EntityTests_MentionSerializationDeserializationTest() { + Mention mentionEntity = new Mention() {{ + setText("TESTTEST"); + }}; + + Assert.assertEquals("mention", mentionEntity.getType()); + + Entity deserializedEntity = new Entity().setAs(mentionEntity); + Assert.assertEquals(deserializedEntity.getType(), mentionEntity.getType()); + Assert.assertEquals(deserializedEntity.getProperties().get("text").textValue(), mentionEntity.getText()); + + Mention mentionDeserialized = deserializedEntity.getAs(Mention.class); + Assert.assertEquals(mentionEntity.getType(), mentionDeserialized.getType()); + Assert.assertEquals(deserializedEntity.getProperties().get("text").textValue(), mentionEntity.getText()); + } + + @Test + public void EntityTests_PlaceSerializationDeserializationTest() { + Place placeEntity = new Place() {{ + setName("TESTTEST"); + }}; + + Assert.assertEquals("Place", placeEntity.getType()); + + Entity deserializedEntity = new Entity().setAs(placeEntity); + Assert.assertEquals(deserializedEntity.getType(), placeEntity.getType()); + + Place placeDeserialized = deserializedEntity.getAs(Place.class); + Assert.assertEquals(placeEntity.getType(), placeDeserialized.getType()); + } +} diff --git a/libraries/swagger/generateClient.cmd b/libraries/swagger/generateClient.cmd index 19b655a71..084eb7361 100644 --- a/libraries/swagger/generateClient.cmd +++ b/libraries/swagger/generateClient.cmd @@ -11,7 +11,7 @@ call .\node_modules\.bin\replace "import com.microsoft.bot.schema.models.ErrorRe call .\node_modules\.bin\replace "import com.microsoft.bot.schema.ConnectorClient;" "import com.microsoft.bot.connector.ConnectorClient;" . -r -q --include="*.java" call .\node_modules\.bin\replace "import com.microsoft.bot.schema.Attachments;" "import com.microsoft.bot.connector.Attachments;" . -r -q --include="*.java" call .\node_modules\.bin\replace "import com.microsoft.bot.schema.Conversations;" "import com.microsoft.bot.connector.Conversations;" . -r -q --include="*.java" -call .\node_modules\.bin\replace "import com.microsoft.rest.RestException;" "import com.microsoft.rest.RestException;import com.microsoft.bot.schema.models.ErrorResponse;" . -r -q --include="ErrorResponseException.java" +call .\node_modules\.bin\replace "import com.microsoft.rest.RestException;" "import com.microsoft.rest.RestException;import com.microsoft.bot.schema.ErrorResponse;" . -r -q --include="ErrorResponseException.java" call .\node_modules\.bin\replace "package com.microsoft.bot.schema" "package com.microsoft.bot.connector" . -r -q --include="*.java" robocopy .\generated\src\main\java\com\microsoft\bot\schema ..\bot-connector\src\main\java\com\microsoft\bot\connector *.* /e /move diff --git a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java index 9e626450a..f5148deed 100644 --- a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java +++ b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java @@ -9,9 +9,8 @@ import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ActivityTypes; -import com.microsoft.bot.schema.models.ResourceResponse; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; @@ -59,16 +58,12 @@ public void handle(HttpExchange httpExchange) throws IOException { httpExchange.sendResponseHeaders(202, 0); httpExchange.getResponseBody().close(); - if (activity.type().equals(ActivityTypes.MESSAGE)) { + if (activity.getType().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text - ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), this.credentials); - ResourceResponse response = connector.conversations().sendToConversation(activity.conversation().id(), - new Activity() - .withType(ActivityTypes.MESSAGE) - .withText("Echo: " + activity.text()) - .withRecipient(activity.from()) - .withFrom(activity.recipient()) - ); + ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), this.credentials); + connector.conversations().sendToConversation( + activity.getConversation().getId(), + activity.createReply("Echo: " + activity.getText())); } } catch (AuthenticationException ex) { httpExchange.sendResponseHeaders(401, 0); diff --git a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java index ea6820d9e..afd9ed44f 100644 --- a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java +++ b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java @@ -12,8 +12,8 @@ import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ActivityTypes; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.WebServlet; @@ -68,16 +68,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) CompletableFuture authenticateRequest = JwtTokenValidation.authenticateRequest(activity, authHeader, credentialProvider, new SimpleChannelProvider()); authenticateRequest.thenRunAsync(() -> { - if (activity.type().equals(ActivityTypes.MESSAGE)) { + if (activity.getType().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text - ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), this.credentials); - connector.conversations().sendToConversation(activity.conversation().id(), - new Activity() - .withType(ActivityTypes.MESSAGE) - .withText("Echo: " + activity.text()) - .withRecipient(activity.from()) - .withFrom(activity.recipient()) - ); + ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), this.credentials); + connector.conversations().sendToConversation( + activity.getConversation().getId(), + activity.createReply("Echo: " + activity.getText())); } }, ExecutorFactory.getExecutor()).join(); diff --git a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java index 0ea2bc04f..5d36e6740 100644 --- a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java +++ b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java @@ -5,6 +5,7 @@ import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.authentication.*; +import com.microsoft.bot.schema.Activity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -19,8 +20,7 @@ import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.schema.models.Activity; -import com.microsoft.bot.schema.models.ActivityTypes; +import com.microsoft.bot.schema.ActivityTypes; import java.util.concurrent.CompletionException; @@ -66,14 +66,14 @@ public ResponseEntity incoming(@RequestBody Activity activity, try { JwtTokenValidation.authenticateRequest(activity, authHeader, _credentialProvider, new SimpleChannelProvider()) .thenRunAsync(() -> { - if (activity.type().equals(ActivityTypes.MESSAGE)) { - logger.info("Received: " + activity.text()); + if (activity.getType().equals(ActivityTypes.MESSAGE)) { + logger.info("Received: " + activity.getText()); // reply activity with the same text - ConnectorClient connector = new RestConnectorClient(activity.serviceUrl(), _credentials); - connector.conversations().sendToConversation(activity.conversation().id(), - new Activity().withType(ActivityTypes.MESSAGE).withText("Echo: " + activity.text()) - .withRecipient(activity.from()).withFrom(activity.recipient())); + ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), _credentials); + connector.conversations().sendToConversation( + activity.getConversation().getId(), + activity.createReply("Echo: " + activity.getText())); } }, ExecutorFactory.getExecutor()).join(); } catch (CompletionException ex) { From ec656aa7ea808dd6c522cf846c5476c6fd4a3f80 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 09:31:30 -0500 Subject: [PATCH 17/26] Linter fixes, now performing a deep copy in Activity.clone. --- .../builder/TranscriptLoggerMiddleware.java | 8 +- .../bot/builder/TranscriptMiddlewareTest.java | 2 +- .../com/microsoft/bot/schema/Activity.java | 224 +++++++++++++++--- .../microsoft/bot/schema/AnimationCard.java | 6 +- .../com/microsoft/bot/schema/Attachment.java | 32 +++ .../com/microsoft/bot/schema/AudioCard.java | 6 +- .../com/microsoft/bot/schema/CardAction.java | 32 +++ .../microsoft/bot/schema/ChannelAccount.java | 31 +++ .../bot/schema/ConversationAccount.java | 55 +++-- .../bot/schema/ConversationReference.java | 15 ++ .../java/com/microsoft/bot/schema/Entity.java | 37 ++- .../com/microsoft/bot/schema/MediaCard.java | 3 +- .../microsoft/bot/schema/MessageReaction.java | 25 ++ .../bot/schema/MicrosoftPayMethodData.java | 2 +- .../bot/schema/SuggestedActions.java | 32 +++ .../com/microsoft/bot/schema/VideoCard.java | 3 +- .../microsoft/bot/schema/ActivityTest.java | 125 +++++++++- .../microsoft/bot/schema/CardActionTest.java | 24 ++ 18 files changed, 592 insertions(+), 70 deletions(-) create mode 100644 libraries/bot-schema/src/test/java/com/microsoft/bot/schema/CardActionTest.java diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java index 68ca44c71..3a32ce99c 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/TranscriptLoggerMiddleware.java @@ -73,9 +73,9 @@ public void OnTurn(TurnContext context, NextDelegate next) throws Exception { if (role == null || StringUtils.isBlank(role.asText())) { context.getActivity().getFrom().getProperties().put("role", mapper.createObjectNode().with("user")); } - Activity activityTemp = Activity.cloneActivity(context.getActivity()); + Activity activityTemp = Activity.clone(context.getActivity()); - LogActivity(Activity.cloneActivity(context.getActivity())); + LogActivity(Activity.clone(context.getActivity())); } // hook up onSend pipeline @@ -93,7 +93,7 @@ public void OnTurn(TurnContext context, NextDelegate next) throws Exception { } for (Activity activity : activities) { - LogActivity(Activity.cloneActivity(activity)); + LogActivity(Activity.clone(activity)); } return responses; @@ -119,7 +119,7 @@ public void OnTurn(TurnContext context, NextDelegate next) throws Exception { } // add Message Update activity - Activity updateActivity = Activity.cloneActivity(activity); + Activity updateActivity = Activity.clone(activity); updateActivity.setType(ActivityTypes.MESSAGE_UPDATE); LogActivity(updateActivity); return response; diff --git a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java index 523ef21a0..69f8ea493 100644 --- a/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java +++ b/libraries/bot-builder/src/test/java/com/microsoft/bot/builder/TranscriptMiddlewareTest.java @@ -190,7 +190,7 @@ public void Transcript_LogUpdateActivities() throws InterruptedException, Execut activity.setId(response.getId()); // clone the activity, so we can use it to do an update - activityToUpdate[0] = Activity.cloneActivity(activity); + activityToUpdate[0] = Activity.clone(activity); //JsonConvert.DeserializeObject(JsonConvert.SerializeObject(activity)); } }).Send("foo") diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java index e6a039cd5..f173d65d2 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java @@ -32,36 +32,37 @@ public class Activity { private static final ObjectMapper MAPPER = new ObjectMapper(); /** - * The type of the activity. Possible values include: 'message', - * 'contactRelationUpdate', 'conversationUpdate', 'typing', 'ping', - * 'endOfConversation', 'event', 'invoke', 'deleteUserData', - * 'messageUpdate', 'messageDelete', 'installationUpdate', - * 'messageReaction', 'suggestion', 'trace'. + * The {@link ActivityTypes} of the activity. */ @JsonProperty(value = "type") private ActivityTypes type; + /** * Contains an ID that uniquely identifies the activity on the channel. */ @JsonProperty(value = "id") private String id; + /** * Contains the date and time that the message was sent, in UTC, expressed in ISO-8601 format. */ @JsonProperty(value = "timestamp") private DateTime timestamp; + /** * Contains the local date and time of the message, expressed in ISO-8601 format. * For example, 2016-09-23T13:07:49.4714686-07:00. */ @JsonProperty(value = "localTimestamp") private DateTime localTimestamp; + /** * Contains the name of the local timezone of the message, expressed in IANA Time Zone database format. * For example, America/Los_Angeles. */ @JsonProperty(value = "localTimezone") private String localTimezone; + /** * A string containing an IRI identifying the caller of a bot. This field is not intended to be transmitted * over the wire, but is instead populated by bots and clients based on cryptographically verifiable data @@ -69,72 +70,86 @@ public class Activity { */ @JsonProperty(value = "callerId") private String callerId; + /** * Contains the URL that specifies the channel's service endpoint. Set by the channel. */ @JsonProperty(value = "serviceUrl") private String serviceUrl; + /** * Contains an ID that uniquely identifies the channel. Set by the channel. */ @JsonProperty(value = "channelId") private String channelId; + /** * Identifies the sender of the message. */ @JsonProperty(value = "from") private ChannelAccount from; + /** * Identifies the conversation to which the activity belongs. */ @JsonProperty(value = "conversation") private ConversationAccount conversation; + /** * Identifies the recipient of the message. */ @JsonProperty(value = "recipient") private ChannelAccount recipient; + /** * Format of text fields Default:markdown. Possible values include: * 'markdown', 'plain', 'xml'. */ @JsonProperty(value = "textFormat") private TextFormatTypes textFormat; + /** * The layout hint for multiple attachments. Default: list. */ @JsonProperty(value = "attachmentLayout") private AttachmentLayoutTypes attachmentLayout; + /** * The collection of members added to the conversation. */ @JsonProperty(value = "membersAdded") private List membersAdded; + /** * The collection of members removed from the conversation. */ @JsonProperty(value = "membersRemoved") private List membersRemoved; + /** * The collection of reactions added to the conversation. */ @JsonProperty(value = "reactionsAdded") private List reactionsAdded; + /** * The collection of reactions removed from the conversation. */ @JsonProperty(value = "reactionsRemoved") private List reactionsRemoved; + /** * The updated topic name of the conversation. */ @JsonProperty(value = "topicName") private String topicName; + /** * Indicates whether the prior history of the channel is disclosed. */ @JsonProperty(value = "historyDisclosed") private boolean historyDisclosed; + /** * A locale name for the contents of the text field. * The locale name is a combination of an ISO 639 two- or three-letter culture code associated with a language @@ -144,16 +159,19 @@ public class Activity { */ @JsonProperty(value = "locale") private String locale; + /** * The text content of the message. */ @JsonProperty(value = "text") private String text; + /** * The text to speak. */ @JsonProperty(value = "speak") private String speak; + /** * Indicates whether your bot is accepting, expecting, or ignoring user input after the message * is delivered to the client. @@ -165,21 +183,25 @@ public class Activity { */ @JsonProperty(value = "summary") private String summary; + /** * The suggested actions for the activity. */ @JsonProperty(value = "suggestedActions") private SuggestedActions suggestedActions; + /** * Attachments. */ @JsonProperty(value = "attachments") private List attachments; + /** * Represents the entities that were mentioned in the message. */ @JsonProperty(value = "entities") private List entities; + /** * Contains channel-specific content. */ @@ -190,51 +212,61 @@ public class Activity { */ @JsonProperty(value = "action") private String action; + /** * Contains the ID of the message to which this message is a reply. */ @JsonProperty(value = "replyToId") private String replyToId; + /** * A descriptive label for the activity. */ @JsonProperty(value = "label") private String label; + /** * The type of the activity's value object. */ @JsonProperty(value = "valueType") private String valueType; + /** * A value that is associated with the activity. */ @JsonProperty(value = "value") private Object value; + /** * The name of the operation associated with an invoke or event activity. */ @JsonProperty(value = "name") private String name; + /** * A reference to another conversation or activity. */ @JsonProperty(value = "relatesTo") private ConversationReference relatesTo; + /** * The a code for endOfConversation activities that indicates why the conversation ended. */ @JsonProperty(value = "code") private EndOfConversationCodes code; + /** * The time at which the activity should be considered to be expired and should not be presented to the recipient. */ @JsonProperty(value = "expiration") private DateTime expiration; + /** * The importance of the activity. */ @JsonProperty(value = "importance") private String importance; + /** * A delivery hint to signal to the recipient alternate delivery paths for the activity. *

@@ -242,16 +274,19 @@ public class Activity { */ @JsonProperty(value = "deliveryMode") private String deliveryMode; + /** * List of phrases and references that speech and language priming systems should listen for. */ @JsonProperty(value = "listenFor") private List listenFor; + /** * The collection of text fragments to highlight when the activity contains a ReplyToId value. */ @JsonProperty(value = "textHighlights") private List textHighlights; + /** * Holds the overflow properties that aren't first class * properties in the object. This allows extensibility @@ -366,38 +401,46 @@ public static Activity createInvokeActivity() { * @param activity The activity to clone. * @return new cloned activity */ - public static Activity cloneActivity(Activity activity) { - //TODO: This isn't a deep copy + public static Activity clone(Activity activity) { Activity clone = new Activity(activity.getType()) {{ setId(activity.getId()); setTimestamp(activity.getTimestamp()); setLocalTimestamp(activity.getLocalTimestamp()); + setLocalTimeZone(activity.getLocalTimezone()); setChannelData(activity.getChannelData()); - setFrom(activity.getFrom()); - setRecipient(activity.getRecipient()); - setConversation(activity.getConversation()); + setFrom(ChannelAccount.clone(activity.getFrom())); + setRecipient(ChannelAccount.clone(activity.getRecipient())); + setConversation(ConversationAccount.clone(activity.getConversation())); setChannelId(activity.getChannelId()); setServiceUrl(activity.getServiceUrl()); setChannelId(activity.getChannelId()); - setEntities(activity.getEntities()); + setEntities(Entity.cloneList(activity.getEntities())); setReplyToId(activity.getReplyToId()); setSpeak(activity.getSpeak()); setText(activity.getText()); setInputHint(activity.getInputHint()); setSummary(activity.getSummary()); - setSuggestedActions(activity.getSuggestedActions()); - setAttachments(activity.getAttachments()); + setSuggestedActions(SuggestedActions.clone(activity.getSuggestedActions())); + setAttachments(Attachment.cloneList(activity.getAttachments())); setAction(activity.getAction()); setLabel(activity.getLabel()); setValueType(activity.getValueType()); setValue(activity.getValue()); setName(activity.getName()); - setRelatesTo(activity.getRelatesTo()); + setRelatesTo(ConversationReference.clone(activity.getRelatesTo())); setCode(activity.getCode()); setExpiration(activity.getExpiration()); setImportance(activity.getImportance()); setDeliveryMode(activity.getDeliveryMode()); setTextHighlights(activity.getTextHighlights()); + setCallerId(activity.getCallerId()); + setHistoryDisclosed(activity.getHistoryDisclosed()); + setLocale(activity.getLocale()); + setReactionsAdded(MessageReaction.cloneList(activity.getReactionsAdded())); + setReactionsRemoved(MessageReaction.cloneList(activity.getReactionsRemoved())); + setExpiration(activity.getExpiration()); + setMembersAdded(ChannelAccount.cloneList(activity.getMembersAdded())); + setMembersRemoved(ChannelAccount.cloneList(activity.getMembersRemoved())); }}; for (Map.Entry entry : activity.getProperties().entrySet()) { @@ -997,27 +1040,73 @@ public void setAction(String withAction) { this.action = withAction; } + /** + * Creates an instance of the Activity class as type {@link ActivityTypes#TRACE}. + * + * @param withName The name of the trace operation to create. + * @return >The new trace activity. + */ + public Activity createTrace(String withName) { + return createTrace(withName, null, null, null); + } + + /** + * Creates an instance of the Activity class as type {@link ActivityTypes#TRACE}. + * + * @param withName The name of the trace operation to create. + * @param withValue Optional, the content for this trace operation. + * @param withValueType Optional, identifier for the format of withValue. Default is the name of type of + * the withValue. + * @param withLabel Optional, a descriptive label for this trace operation. + * @return >The new trace activity. + */ public Activity createTrace(String withName, Object withValue, String withValueType, String withLabel) { Activity reply = new Activity(ActivityTypes.TRACE); reply.setName(withName); reply.setLabel(withLabel); - reply.setValueType((withValueType == null) ? withValue.getClass().getTypeName() : withValueType); + + if (withValueType != null) { + reply.setValueType(withValueType); + } else { + reply.setValueType((withValue != null) ? withValue.getClass().getTypeName() : null); + } reply.setValue(withValue); - reply.setFrom(new ChannelAccount(this.getRecipient().getId(), this.getRecipient().getName())); - reply.setRecipient(new ChannelAccount(this.getFrom().getId(), this.getFrom().getName())); + if (this.getRecipient() == null) { + reply.setFrom(new ChannelAccount()); + } else { + reply.setFrom(new ChannelAccount(this.getRecipient().getId(), this.getRecipient().getName())); + } + + if (this.getFrom() == null) { + reply.setRecipient(new ChannelAccount()); + } else { + reply.setRecipient(new ChannelAccount(this.getFrom().getId(), this.getFrom().getName())); + } + reply.setReplyToId(this.getId()); reply.setServiceUrl(this.getServiceUrl()); reply.setChannelId(this.getChannelId()); - reply.setConversation(new ConversationAccount( - this.getConversation().isGroup(), - this.getConversation().getId(), - this.getConversation().getName())); + + if (this.getConversation() != null) { + reply.setConversation(new ConversationAccount( + this.getConversation().isGroup(), + this.getConversation().getId(), + this.getConversation().getName())); + } return reply; } + /** + * Creates a new message activity as a response to this activity. + * + * This overload uses this Activity's Locale. + * + * @param withText The text of the reply. + * @return The new message activity. + */ public Activity createReply(String withText) { return createReply(withText, null); } @@ -1034,19 +1123,36 @@ public Activity createReply(String withText, String withLocale) { result.setText((withText == null) ? "" : withText); result.setLocale((withLocale == null) ? this.getLocale() : withLocale); - result.setFrom(new ChannelAccount( - this.getRecipient().getId(), - this.getRecipient().getName())); - result.setRecipient(new ChannelAccount( - this.getFrom().getId(), - this.getFrom().getName())); + + if (this.getRecipient() == null) { + result.setFrom(new ChannelAccount()); + } else { + result.setFrom(new ChannelAccount( + this.getRecipient().getId(), + this.getRecipient().getName())); + } + + if (this.getFrom() == null) { + result.setRecipient(new ChannelAccount()); + } else { + result.setRecipient(new ChannelAccount( + this.getFrom().getId(), + this.getFrom().getName())); + } + result.setReplyToId(this.getId()); result.setServiceUrl(this.getServiceUrl()); result.setChannelId(this.getChannelId()); - result.setConversation(new ConversationAccount( - this.getConversation().isGroup(), - this.getConversation().getId(), - this.getConversation().getName())); + + if (this.getConversation() == null) { + result.setConversation(new ConversationAccount()); + } else { + result.setConversation(new ConversationAccount( + this.getConversation().isGroup(), + this.getConversation().getId(), + this.getConversation().getName())); + } + result.setAttachments(new ArrayList<>()); result.setEntities(new ArrayList<>()); @@ -1122,6 +1228,33 @@ public ResultPair tryGetChannelData(Class clsType return new ResultPair(true, instance); } + /** + * Creates a {@link ConversationReference} based on this activity. + * @return A conversation reference for the conversation that contains this activity. + */ + public ConversationReference getConversationReference() { + return new ConversationReference() {{ + setActivityId(Activity.this.getId()); + setUser(Activity.this.getFrom()); + setBot(Activity.this.getRecipient()); + setConversation(Activity.this.getConversation()); + setChannelId(Activity.this.getChannelId()); + setServiceUrl(Activity.this.getServiceUrl()); + }}; + } + + /** + * Create a ConversationReference based on this Activity's Conversation info and the ResourceResponse + * from sending an activity. + * @param reply ResourceResponse returned from sendActivity. + * @return A ConversationReference that can be stored and used later to delete or update the activity. + */ + public ConversationReference getReplyConversationReference(ResourceResponse reply) { + ConversationReference reference = getConversationReference(); + reference.setActivityId(reply.getId()); + return reference; + } + /** * True if the Activity is of the specified activity type */ @@ -1143,17 +1276,17 @@ protected boolean isActivity(String activityType) { } // Check if the full type value starts with the type they're looking for - - boolean result = StringUtils.startsWith(type.toString().toLowerCase(), activityType.toLowerCase()); - // If the full type value starts with the type they're looking for, then we need to check a little further to check if it's definitely the right type + // If the full type value starts with the type they're looking for, then we need to check a little further + // to check if it's definitely the right type if (result) { // If the lengths are equal, then it's the exact type they're looking for result = type.toString().length() == activityType.length(); if (!result) { - // Finally, if the type is longer than the type they're looking for then we need to check if there's a / separator right after the type they're looking for + // Finally, if the type is longer than the type they're looking for then we need to check if there's + // a / separator right after the type they're looking for result = type.toString().length() > activityType.length() && type.toString().indexOf(activityType.length()) == '/'; @@ -1163,10 +1296,27 @@ protected boolean isActivity(String activityType) { return result; } + /** + * Updates this activity with the outgoing delivery information from an existing {@link ConversationReference}. + * + * @param reference The existing conversation reference. + * @return This activity, updated with the delivery information. + */ public final Activity applyConversationReference(ConversationReference reference) { return applyConversationReference(reference, false); } + /** + * Updates this activity with the delivery information from an existing {@link ConversationReference}. + * + * Call {@link #getConversationReference} on an incoming activity to get a conversation reference that you + * can then use to update an outgoing activity with the correct delivery information. + * + * @param reference The existing conversation reference. + * @param isIncoming true to treat the activity as an incoming activity, where the bot is the recipient; + * otherwise, false. + * @return This activity, updated with the delivery information. + */ public final Activity applyConversationReference(ConversationReference reference, boolean isIncoming) { this.setChannelId(reference.getChannelId()); this.setServiceUrl(reference.getServiceUrl()); @@ -1178,14 +1328,14 @@ public final Activity applyConversationReference(ConversationReference reference if (reference.getActivityId() != null) { this.setId(reference.getActivityId()); } - } else // Outgoing - { + } else { this.setFrom(reference.getBot()); this.setRecipient(reference.getUser()); if (reference.getActivityId() != null) { this.setReplyToId(reference.getActivityId()); } } + return this; } } diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java index ab61d4cf1..8198d49bb 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AnimationCard.java @@ -39,7 +39,8 @@ public class AnimationCard { private ThumbnailUrl image; /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + * Media URLs for this card. When this field contains more than one URL, each URL is an alternative + * format of the same content. */ @JsonProperty(value = "media") private List media; @@ -77,7 +78,8 @@ public class AnimationCard { private String aspect; /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + * Describes the length of the media content without requiring a receiver to open the content. Formatted as + * an ISO 8601 Duration field. */ @JsonProperty(value = "duration") private String duration; diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java index 4f255f321..074422b92 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Attachment.java @@ -11,8 +11,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * An attachment within an activity. @@ -54,6 +57,35 @@ public class Attachment { */ private HashMap properties = new HashMap(); + public static Attachment clone(Attachment attachment) { + if (attachment == null) { + return null; + } + + return new Attachment() {{ + setContentType(attachment.getContentType()); + setContent(attachment.getContent()); + setContentUrl(attachment.getContentUrl()); + setName(attachment.getName()); + setThumbnailUrl(attachment.getThumbnailUrl()); + + for (String key : attachment.getProperties().keySet()) { + this.setProperties(key, attachment.getProperties().get(key)); + } + }}; + } + + public static List cloneList(List attachments) { + if (attachments == null) { + return null; + } + + return attachments.stream() + .map(attachment -> Attachment.clone(attachment)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + /** * Get the contentType value. * diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java index 6adea2802..8641062fd 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/AudioCard.java @@ -39,7 +39,8 @@ public class AudioCard { private ThumbnailUrl image; /** - * Media URLs for this card. When this field contains more than one URL, each URL is an alternative format of the same content. + * Media URLs for this card. When this field contains more than one URL, each URL is an + * alternative format of the same content. */ @JsonProperty(value = "media") private List media; @@ -77,7 +78,8 @@ public class AudioCard { private String aspect; /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + * Describes the length of the media content without requiring a receiver to open the content. Formatted as an + * ISO 8601 Duration field. */ @JsonProperty(value = "duration") private String duration; diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java index 2a1b12976..d8a84ee58 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/CardAction.java @@ -57,6 +57,38 @@ public class CardAction { @JsonProperty(value = "channelData") private Object channelData; + public static CardAction clone(CardAction cardAction) { + if (cardAction == null) { + return null; + } + + return new CardAction() {{ + setValue(cardAction.getValue()); + setTitle(cardAction.getTitle()); + setDisplayText(cardAction.getDisplayText()); + setImage(cardAction.getImage()); + setType(cardAction.getType()); + setText(cardAction.getText()); + setChannelData(cardAction.getChannelData()); + }}; + } + + /** + * Default empty CardAction + */ + public CardAction() { + + } + + /** + * Simplify creation of CardActions with string values. + * @param input + */ + public CardAction(String input) { + setTitle(input); + setValue(input); + } + /** * Get the type value. * diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java index f42945396..7934546b5 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ChannelAccount.java @@ -11,8 +11,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * Channel account information needed to route a message. @@ -51,6 +54,34 @@ public class ChannelAccount { */ private HashMap properties = new HashMap(); + public static ChannelAccount clone(ChannelAccount channelAccount) { + if (channelAccount == null) { + return null; + } + + return new ChannelAccount() {{ + setId(channelAccount.getId()); + setRole(channelAccount.getRole()); + setName(channelAccount.getName()); + setAadObjectId(channelAccount.getAadObjectId()); + + for (String key : channelAccount.getProperties().keySet()) { + this.setProperties(key, channelAccount.getProperties().get(key)); + } + }}; + } + + public static List cloneList(List channelAccounts) { + if (channelAccounts == null) { + return null; + } + + return channelAccounts.stream() + .map(channelAccount -> ChannelAccount.clone(channelAccount)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + /** * Initializes a new instance of the ChannelAccount class. */ diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java index 53f5e6990..4e94f04ea 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationAccount.java @@ -6,7 +6,13 @@ package com.microsoft.bot.schema; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.HashMap; +import java.util.Map; /** * Conversation account represents the identity of the conversation within a channel. @@ -80,7 +86,8 @@ public ConversationAccount(String withId) { * @param withName Display friendly name. */ public ConversationAccount(boolean withIsGroup, String withId, String withName) { - this(withIsGroup, null, withId, withName, null, null, null); + this(withIsGroup, null, withId, withName, + null, null, null); } /** @@ -97,7 +104,8 @@ public ConversationAccount(boolean withIsGroup, String withId, String withName) * include: 'user', 'bot'. * @param withTenantId This conversation's tenant ID. */ - public ConversationAccount(boolean withIsGroup, String withConversationType, String withId, String withName, String withAadObjectId, RoleTypes withRole, String withTenantId) { + public ConversationAccount(boolean withIsGroup, String withConversationType, String withId, String withName, + String withAadObjectId, RoleTypes withRole, String withTenantId) { this.isGroup = withIsGroup; this.conversationType = withConversationType; this.id = withId; @@ -223,9 +231,28 @@ public void setRole(RoleTypes withRole) { * Holds the overflow properties that aren't first class * properties in the object. This allows extensibility * while maintaining the object. - * */ -// private HashMap properties = new HashMap(); + private HashMap properties = new HashMap(); + + public static ConversationAccount clone(ConversationAccount conversationAccount) { + if (conversationAccount == null) { + return null; + } + + return new ConversationAccount() {{ + setId(conversationAccount.getId()); + setName(conversationAccount.getName()); + setIsGroup(conversationAccount.isGroup()); + setConversationType(conversationAccount.getConversationType()); + setAadObjectId(conversationAccount.getAadObjectId()); + setRole(conversationAccount.getRole()); + setAadObjectId(conversationAccount.getAadObjectId()); + + for (String key : conversationAccount.getProperties().keySet()) { + this.setProperties(key, conversationAccount.getProperties().get(key)); + } + }}; + } /** * Overflow properties. @@ -234,20 +261,20 @@ public void setRole(RoleTypes withRole) { * * @return A Key-Value map of the properties */ -// @JsonAnyGetter -// public Map properties() { -// return this.properties; -// } + @JsonAnyGetter + public Map getProperties() { + return this.properties; + } /** * Set overflow properties. * - * @param key Key for the property + * @param key Key for the property * @param value JsonNode of value (can be nested) - * */ -// @JsonAnySetter -// public void setProperties(String key, JsonNode value) { -// this.properties.put(key, value); -// } + @JsonAnySetter + public void setProperties(String key, JsonNode value) { + + this.properties.put(key, value); + } } diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java index b0ba5aa8f..a66beb6d2 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/ConversationReference.java @@ -49,6 +49,21 @@ public class ConversationReference { @JsonProperty(value = "serviceUrl") private String serviceUrl; + public static ConversationReference clone(ConversationReference conversationReference) { + if (conversationReference == null) { + return null; + } + + return new ConversationReference() {{ + setActivityId(conversationReference.getActivityId()); + setBot(ChannelAccount.clone(conversationReference.getBot())); + setUser(ChannelAccount.clone(conversationReference.getUser())); + setConversation(ConversationAccount.clone(conversationReference.getConversation())); + setServiceUrl(conversationReference.getServiceUrl()); + setChannelId(conversationReference.getChannelId()); + }}; + } + /** * Get the activityId value. * diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java index 18e06d130..5d2c5bd94 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Entity.java @@ -14,8 +14,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * Metadata object pertaining to an activity. @@ -33,6 +36,30 @@ public class Entity { @JsonProperty(value = "type") private String type; + public static Entity clone(Entity entity) { + if (entity == null) { + return null; + } + + return new Entity() {{ + setType(entity.getType()); + + for (String key : entity.getProperties().keySet()) { + setProperties(key, entity.getProperties().get(key)); + } + }}; + } + + public static List cloneList(List entities) { + if (entities == null) { + return null; + } + + return entities.stream() + .map(entity -> Entity.clone(entity)) + .collect(Collectors.toCollection(ArrayList::new)); + } + /** * Get the {@link #type} value. * @return the type value @@ -66,10 +93,10 @@ public void setProperties(String key, JsonNode value) { } /** - * Retrieve internal payload. + * Converts Entity to other Entity types. * - * @param classType of type T - * @return + * @param classType Class extended EntitySerialization + * @return Entity converted to type T */ public T getAs(Class classType) { @@ -95,9 +122,9 @@ public T getAs(Class classType) { } /** - * Set internal payload. + * Converts other Entity types to Entity. * - * This is only intended to be used with other Enitity classes: + * This is only intended to be used with other Entity classes: * @see Mention * @see Place * @see GeoCoordinates diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java index 19ff7cbbc..a414259d9 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MediaCard.java @@ -77,7 +77,8 @@ public class MediaCard { private String aspect; /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + * Describes the length of the media content without requiring a receiver to open the content. + * Formatted as an ISO 8601 Duration field. */ @JsonProperty(value = "duration") private String duration; diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java index 954acf1e4..ee63777d2 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MessageReaction.java @@ -8,6 +8,10 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + /** * Message reaction object. */ @@ -18,6 +22,27 @@ public class MessageReaction { @JsonProperty(value = "type") private MessageReactionTypes type; + public static MessageReaction clone(MessageReaction messageReaction) { + if (messageReaction == null) { + return null; + } + + return new MessageReaction() {{ + setType(messageReaction.getType()); + }}; + } + + public static List cloneList(List messageReactions) { + if (messageReactions == null) { + return null; + } + + return messageReactions.stream() + .map(messageReaction -> MessageReaction.clone(messageReaction)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + /** * Get the type value. * diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java index ea121e3b7..3c5bdcc68 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/MicrosoftPayMethodData.java @@ -44,7 +44,7 @@ public String getMerchantId() { /** * Set the merchantId value. * - * @param merchantId the merchantId value to set + * @param withMerchantId the merchantId value to set * @return the MicrosoftPayMethodData object itself. */ public void setMerchantId(String withMerchantId) { diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java index 58e0361ec..81771b5a7 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/SuggestedActions.java @@ -8,7 +8,10 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * SuggestedActions that can be performed. @@ -28,6 +31,35 @@ public class SuggestedActions { @JsonProperty(value = "actions") private List actions; + public static SuggestedActions clone(SuggestedActions suggestedActions) { + if (suggestedActions == null) { + return null; + } + + return new SuggestedActions() {{ + setTo(suggestedActions.getTo()); + + setActions(suggestedActions.getActions().stream() + .map(card -> CardAction.clone(card)) + .collect(Collectors.toCollection(ArrayList::new))); + }}; + } + + /** + * Default empty SuggestedActions + */ + public SuggestedActions() { + + } + + /** + * + * @param withCardActions + */ + public SuggestedActions(CardAction[] withCardActions) { + this.setActions(Arrays.asList(withCardActions)); + } + /** * Get the to value. * diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java index 2c8c6aa5e..eb0136a02 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/VideoCard.java @@ -77,7 +77,8 @@ public class VideoCard { private String aspect; /** - * Describes the length of the media content without requiring a receiver to open the content. Formatted as an ISO 8601 Duration field. + * Describes the length of the media content without requiring a receiver to open the content. + * Formatted as an ISO 8601 Duration field. */ @JsonProperty(value = "duration") private String duration; diff --git a/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java index c440939ca..38b4d5f90 100644 --- a/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java +++ b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/ActivityTest.java @@ -1,21 +1,142 @@ package com.microsoft.bot.schema; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.Assert; import org.junit.Test; public class ActivityTest { @Test public void GetConversationReference() { + Activity activity = createActivity(); + ConversationReference conversationReference = activity.getConversationReference(); + Assert.assertEquals(activity.getId(), conversationReference.getActivityId()); + Assert.assertEquals(activity.getFrom().getId(), conversationReference.getUser().getId()); + Assert.assertEquals(activity.getRecipient().getId(), conversationReference.getBot().getId()); + Assert.assertEquals(activity.getConversation().getId(), conversationReference.getConversation().getId()); + Assert.assertEquals(activity.getChannelId(), conversationReference.getChannelId()); + Assert.assertEquals(activity.getServiceUrl(), conversationReference.getServiceUrl()); + } + + @Test + public void GetReplyConversationReference() { + Activity activity = createActivity(); + + ResourceResponse reply = new ResourceResponse() {{ + setId("1234"); + }}; + + ConversationReference conversationReference = activity.getReplyConversationReference(reply); + + Assert.assertEquals(reply.getId(), conversationReference.getActivityId()); + Assert.assertEquals(activity.getFrom().getId(), conversationReference.getUser().getId()); + Assert.assertEquals(activity.getRecipient().getId(), conversationReference.getBot().getId()); + Assert.assertEquals(activity.getConversation().getId(), conversationReference.getConversation().getId()); + Assert.assertEquals(activity.getChannelId(), conversationReference.getChannelId()); + Assert.assertEquals(activity.getServiceUrl(), conversationReference.getServiceUrl()); + } + + @Test + public void ApplyConversationReference_isIncoming() { + Activity activity = createActivity(); + + ConversationReference conversationReference = new ConversationReference() {{ + setChannelId("cr_123"); + setServiceUrl("cr_serviceUrl"); + setConversation(new ConversationAccount(){{ + setId("cr_456"); + }}); + setUser(new ChannelAccount() {{ + setId("cr_abc"); + }}); + setBot(new ChannelAccount() {{ + setId("cr_def"); + }}); + setActivityId("cr_12345"); + }}; + + activity.applyConversationReference(conversationReference, true); + + Assert.assertEquals(conversationReference.getChannelId(), activity.getChannelId()); + Assert.assertEquals(conversationReference.getServiceUrl(), activity.getServiceUrl()); + Assert.assertEquals(conversationReference.getConversation().getId(), activity.getConversation().getId()); + + Assert.assertEquals(conversationReference.getUser().getId(), activity.getFrom().getId()); + Assert.assertEquals(conversationReference.getBot().getId(), activity.getRecipient().getId()); + Assert.assertEquals(conversationReference.getActivityId(), activity.getId()); + } + + @Test + public void ApplyConversationReference() { + Activity activity = createActivity(); + + ConversationReference conversationReference = new ConversationReference() {{ + setChannelId("123"); + setServiceUrl("serviceUrl"); + setConversation(new ConversationAccount(){{ + setId("456"); + }}); + setUser(new ChannelAccount() {{ + setId("abc"); + }}); + setBot(new ChannelAccount() {{ + setId("def"); + }}); + setActivityId("12345"); + }}; + + activity.applyConversationReference(conversationReference, false); + + Assert.assertEquals(conversationReference.getChannelId(), activity.getChannelId()); + Assert.assertEquals(conversationReference.getServiceUrl(), activity.getServiceUrl()); + Assert.assertEquals(conversationReference.getConversation().getId(), activity.getConversation().getId()); + + Assert.assertEquals(conversationReference.getBot().getId(), activity.getFrom().getId()); + Assert.assertEquals(conversationReference.getUser().getId(), activity.getRecipient().getId()); + Assert.assertEquals(conversationReference.getActivityId(), activity.getReplyToId()); + } + + @Test + public void CreateTraceAllowsNullRecipient() { + Activity activity = createActivity(); + activity.setRecipient(null); + Activity trace = activity.createTrace("test"); + + Assert.assertNull(trace.getFrom().getId()); } private Activity createActivity() { ChannelAccount account1 = new ChannelAccount() {{ setId("ChannelAccount_Id_1"); setName("ChannelAccount_Name_1"); - setProperties("Name", JsonNodeFactory.instance.objectNode()); + setProperties("Name", JsonNodeFactory.instance.objectNode().put("Name", "Value")); + setRole(RoleTypes.USER); + }}; + + ChannelAccount account2 = new ChannelAccount() {{ + setId("ChannelAccount_Id_2"); + setName("ChannelAccount_Name_2"); + setProperties("Name", JsonNodeFactory.instance.objectNode().put("Name", "Value")); + setRole(RoleTypes.USER); + }}; + + ConversationAccount conversationAccount = new ConversationAccount() {{ + setConversationType("a"); + setId("123"); + setIsGroup(true); + setName("Name"); + setProperties("Name", JsonNodeFactory.instance.objectNode().put("Name", "Value")); + }}; + Activity activity = new Activity() {{ + setId("123"); + setFrom(account1); + setRecipient(account2); + setConversation(conversationAccount); + setChannelId("ChannelId123"); + setServiceUrl("ServiceUrl123"); }}; + + return activity; } } diff --git a/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/CardActionTest.java b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/CardActionTest.java new file mode 100644 index 000000000..ca8d9ee07 --- /dev/null +++ b/libraries/bot-schema/src/test/java/com/microsoft/bot/schema/CardActionTest.java @@ -0,0 +1,24 @@ +package com.microsoft.bot.schema; + +import org.junit.Assert; +import org.junit.Test; + +public class CardActionTest { + // this really isn't an implicit conversion. it just matches the dotnet + // test. This tests the CardAction[] SuggestedActions constructor. + @Test + public void TestImplicitConversation() { + SuggestedActions actions = new SuggestedActions(new CardAction[] { + new CardAction("x"), + new CardAction("y"), + new CardAction("z") + }); + + Assert.assertEquals("x", actions.getActions().get(0).getTitle()); + Assert.assertEquals("x", actions.getActions().get(0).getValue()); + Assert.assertEquals("y", actions.getActions().get(1).getTitle()); + Assert.assertEquals("y", actions.getActions().get(1).getValue()); + Assert.assertEquals("z", actions.getActions().get(2).getTitle()); + Assert.assertEquals("z", actions.getActions().get(2).getValue()); + } +} From cb5f9056ee37da994153d99e3329198e73bc2e5d Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 10:11:41 -0500 Subject: [PATCH 18/26] Fixed some oddities with ConnectorClient, switched to using standard get/set instead of get/with. --- .../bot/builder/BotFrameworkAdapter.java | 80 ++++++++----------- .../microsoft/bot/connector/AsyncHelper.java | 25 ++++++ .../bot/connector/ConnectorClient.java | 22 +++-- .../bot/connector/rest/RestAttachments.java | 4 +- .../connector/rest/RestConnectorClient.java | 63 ++++++++------- .../bot/connector/rest/RestConversations.java | 63 +++------------ .../bot/connector/AttachmentsTest.java | 14 ++-- .../bot/connector/ConversationsTest.java | 80 +++++++++---------- .../microsoft/bot/connector/sample/App.java | 2 +- .../bot/sample/servlet/EchoServlet.java | 2 +- .../bot/sample/spring/BotController.java | 2 +- 11 files changed, 169 insertions(+), 188 deletions(-) create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java index 8465898fa..cad5b5525 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java @@ -3,12 +3,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import com.microsoft.bot.connector.AsyncHelper; import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.Conversations; import com.microsoft.bot.connector.ExecutorFactory; import com.microsoft.bot.connector.authentication.*; import com.microsoft.bot.connector.rest.RestConnectorClient; -import com.microsoft.bot.connector.rest.RestConversations; import com.microsoft.bot.schema.*; import com.microsoft.rest.retry.RetryStrategy; import org.apache.commons.lang3.StringUtils; @@ -19,7 +19,7 @@ import java.net.URISyntaxException; import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.CompletionException; import java.util.function.Consumer; import java.util.function.Function; @@ -295,10 +295,10 @@ public ResourceResponse[] SendActivities(TurnContext context, Activity[] activit // if it is a Trace activity we only send to the channel if it's the emulator. } else if (!StringUtils.isEmpty(activity.getReplyToId())) { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().replyToActivity(activity.getConversation().getId(), activity.getId(), activity); + response = connectorClient.getConversations().replyToActivity(activity.getConversation().getId(), activity.getId(), activity); } else { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); - response = connectorClient.conversations().sendToConversation(activity.getConversation().getId(), activity); + response = connectorClient.getConversations().sendToConversation(activity.getConversation().getId(), activity); } // If No response is set, then defult to a "simple" response. This can't really be done @@ -337,7 +337,7 @@ public ResourceResponse[] SendActivities(TurnContext context, Activity[] activit public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { ConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); // TODO String conversationId, String activityId, Activity activity) - return connectorClient.conversations().updateActivity(activity.getConversation().getId(), activity.getId(), activity); + return connectorClient.getConversations().updateActivity(activity.getConversation().getId(), activity.getId(), activity); } /** @@ -346,18 +346,15 @@ public ResourceResponse UpdateActivity(TurnContext context, Activity activity) { * @param context The context object for the turn. * @param reference Conversation reference for the activity to delete. * @return A task that represents the work queued to execute. - * The {@link ConversationReference.ActivityId} of the conversation - * reference identifies the activity to delete. * {@linkalso TurnContext.OnDeleteActivity(DeleteActivityHandler)} */ public void DeleteActivity(TurnContext context, ConversationReference reference) { RestConnectorClient connectorClient = context.getServices().Get("ConnectorClient"); try { - connectorClient.conversations().deleteConversationMemberFuture(reference.getConversation().getId(), reference.getActivityId()).join(); - } catch (ExecutionException e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); - } catch (InterruptedException e) { + AsyncHelper.completableSingleFutureFromObservable( + connectorClient.getConversations().deleteConversationMemberAsync( + reference.getConversation().getId(), reference.getActivityId())).join(); + } catch (CompletionException e) { e.printStackTrace(); throw new RuntimeException(String.format("Failed deleting activity (%s)", e.toString())); } @@ -590,43 +587,32 @@ public CompletableFuture CreateConversation(String channelId, String serviceUrl, throw new RuntimeException(String.format("Bad serviceUrl: %s", serviceUrl)); } - Conversations conv = connectorClient.conversations(); - List results = null; - if (conv instanceof RestConversations) { - RestConversations convImpl = (RestConversations) conv; - results = convImpl.CreateConversationAsync(conversationParameters).join(); - } else { - results = new ArrayList(); - results.add(conv.createConversation(conversationParameters)); - } - if (results.size() == 1) { - - ConversationResourceResponse result = results.get(0); - // Create a conversation update activity to represent the result. - - Activity conversationUpdate = Activity.createConversationUpdateActivity(); - conversationUpdate.setChannelId(channelId); - conversationUpdate.setTopicName(conversationParameters.getTopicName()); - conversationUpdate.setServiceUrl(serviceUrl); - conversationUpdate.setMembersAdded(conversationParameters.getMembers()); - conversationUpdate.setId((result.getActivityId() != null) ? result.getActivityId() : UUID.randomUUID().toString()); - conversationUpdate.setConversation(new ConversationAccount(result.getId())); - conversationUpdate.setRecipient(conversationParameters.getBot()); - - try (TurnContextImpl context = new TurnContextImpl(this, conversationUpdate)) { - try { - this.RunPipeline(context, callback); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format("Running pipeline failed : %s", e)); - } + Conversations conversations = connectorClient.getConversations(); + CompletableFuture result = AsyncHelper.completableSingleFutureFromObservable( + conversations.createConversationAsync(conversationParameters)); + + ConversationResourceResponse response = result.join(); + + // Create a conversation update activity to represent the result. + Activity conversationUpdate = Activity.createConversationUpdateActivity(); + conversationUpdate.setChannelId(channelId); + conversationUpdate.setTopicName(conversationParameters.getTopicName()); + conversationUpdate.setServiceUrl(serviceUrl); + conversationUpdate.setMembersAdded(conversationParameters.getMembers()); + conversationUpdate.setId((response.getActivityId() != null) ? response.getActivityId() : UUID.randomUUID().toString()); + conversationUpdate.setConversation(new ConversationAccount(response.getId())); + conversationUpdate.setRecipient(conversationParameters.getBot()); + + try (TurnContextImpl context = new TurnContextImpl(this, conversationUpdate)) { + try { + this.RunPipeline(context, callback); } catch (Exception e) { e.printStackTrace(); - throw new RuntimeException(String.format("Turn Context Error: %s", e)); + throw new RuntimeException(String.format("Running pipeline failed : %s", e)); } - } else { - // Should never happen - throw new RuntimeException(String.format("Conversations create issue - returned %d conversations", results.size())); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Turn Context Error: %s", e)); } }, ExecutorFactory.getExecutor()); @@ -746,7 +732,7 @@ private ConnectorClient CreateConnectorClient(String serviceUrl, MicrosoftAppCre // } if (this.connectorClientRetryStrategy != null) - connectorClient.withRestRetryStrategy(this.connectorClientRetryStrategy); + connectorClient.setRestRetryStrategy(this.connectorClientRetryStrategy); return connectorClient; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java new file mode 100644 index 000000000..eeaeedbcf --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java @@ -0,0 +1,25 @@ +package com.microsoft.bot.connector; + +import rx.Observable; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class AsyncHelper { + public static CompletableFuture> completableFutureFromObservable(Observable observable) { + final CompletableFuture> future = new CompletableFuture<>(); + observable + .doOnError(future::completeExceptionally) + .toList() + .forEach(future::complete); + return future; + } + + public static CompletableFuture completableSingleFutureFromObservable(Observable observable) { + final CompletableFuture future = new CompletableFuture<>(); + observable + .doOnError(future::completeExceptionally) + .single(); + return future; + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java index fa7b9b5cb..a2f64abb0 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java @@ -22,7 +22,7 @@ public interface ConnectorClient { * * @return the {@link RestClient} object. */ - RestClient restClient(); + RestClient getRestClient(); /** * Gets the {@link AzureClient} used for long running operations. @@ -35,29 +35,28 @@ public interface ConnectorClient { * * @return the user agent string. */ - String userAgent(); + String getUserAgent(); /** * Gets Gets or sets the preferred language for the response.. * * @return the acceptLanguage value. */ - String acceptLanguage(); + String getAcceptLanguage(); /** * Sets Gets or sets the preferred language for the response.. * * @param acceptLanguage the acceptLanguage value. - * @return the service client itself */ - ConnectorClient withAcceptLanguage(String acceptLanguage); + void setAcceptLanguage(String acceptLanguage); /** * Gets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.. * * @return the longRunningOperationRetryTimeout value. */ - int longRunningOperationRetryTimeout(); + int getLongRunningOperationRetryTimeout(); /** * Sets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30.. @@ -65,14 +64,14 @@ public interface ConnectorClient { * @param longRunningOperationRetryTimeout the longRunningOperationRetryTimeout value. * @return the service client itself */ - ConnectorClient withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout); + void setLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout); /** * Gets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.. * * @return the generateClientRequestId value. */ - boolean generateClientRequestId(); + boolean getGenerateClientRequestId(); /** * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.. @@ -80,18 +79,17 @@ public interface ConnectorClient { * @param generateClientRequestId the generateClientRequestId value. * @return the service client itself */ - ConnectorClient withGenerateClientRequestId(boolean generateClientRequestId); + void setGenerateClientRequestId(boolean generateClientRequestId); /** * Gets the Attachments object to access its operations. * @return the Attachments object. */ - Attachments attachments(); + Attachments getAttachments(); /** * Gets the Conversations object to access its operations. * @return the Conversations object. */ - Conversations conversations(); - + Conversations getConversations(); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java index fa70a3d5d..a29f1f2ae 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java @@ -118,7 +118,7 @@ public Observable> getAttachmentInfoWithServiceR if (attachmentId == null) { throw new IllegalArgumentException("Parameter attachmentId is required and cannot be null."); } - return service.getAttachmentInfo(attachmentId, this.client.acceptLanguage(), this.client.userAgent()) + return service.getAttachmentInfo(attachmentId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -202,7 +202,7 @@ public Observable> getAttachmentWithServiceResponse if (viewId == null) { throw new IllegalArgumentException("Parameter viewId is required and cannot be null."); } - return service.getAttachment(attachmentId, viewId, this.client.acceptLanguage(), this.client.userAgent()) + return service.getAttachment(attachmentId, viewId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java index ca92b46e4..41399a77a 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java @@ -11,6 +11,7 @@ import com.microsoft.azure.AzureServiceClient; import com.microsoft.bot.connector.Attachments; import com.microsoft.bot.connector.ConnectorClient; +import com.microsoft.bot.connector.Conversations; import com.microsoft.rest.credentials.ServiceClientCredentials; import com.microsoft.rest.RestClient; import com.microsoft.rest.retry.RetryStrategy; @@ -49,44 +50,44 @@ public class RestConnectorClient extends AzureServiceClient implements Connector * Gets the {@link AzureClient} used for long running operations. * @return the azure client; */ + @Override public AzureClient getAzureClient() { return this.azureClient; } + @Override + public RestClient getRestClient() { + return super.restClient(); + } + /** Gets or sets the preferred language for the response. */ private String acceptLanguage; private String user_agent_string; /** - * Gets Gets or sets the preferred language for the response. - * - * @return the acceptLanguage value. + * @see ConnectorClient#getAcceptLanguage() */ - public String acceptLanguage() { + @Override + public String getAcceptLanguage() { return this.acceptLanguage; } /** - * Sets Gets or sets the preferred language for the response. - * - * @param acceptLanguage the acceptLanguage value. - * @return the service client itself + * @see ConnectorClient#setAcceptLanguage(String) */ - public RestConnectorClient withAcceptLanguage(String acceptLanguage) { + @Override + public void setAcceptLanguage(String acceptLanguage) { this.acceptLanguage = acceptLanguage; - return this; } /** * RetryStrategy as defined in Microsoft Rest Retry - * TODO: Use this. */ private RetryStrategy retryStrategy = null; - public RestConnectorClient withRestRetryStrategy(RetryStrategy retryStrategy) { + public void setRestRetryStrategy(RetryStrategy retryStrategy) { this.retryStrategy = retryStrategy; - return this; } - public RetryStrategy restRetryStrategy() { + public RetryStrategy getRestRetryStrategy() { return this.retryStrategy; } @@ -98,7 +99,8 @@ public RetryStrategy restRetryStrategy() { * * @return the longRunningOperationRetryTimeout value. */ - public int longRunningOperationRetryTimeout() { + @Override + public int getLongRunningOperationRetryTimeout() { return this.longRunningOperationRetryTimeout; } @@ -106,11 +108,10 @@ public int longRunningOperationRetryTimeout() { * Sets Gets or sets the retry timeout in seconds for Long Running Operations. Default value is 30. * * @param longRunningOperationRetryTimeout the longRunningOperationRetryTimeout value. - * @return the service client itself */ - public RestConnectorClient withLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) { + @Override + public void setLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout) { this.longRunningOperationRetryTimeout = longRunningOperationRetryTimeout; - return this; } /** When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true. */ @@ -121,7 +122,8 @@ public RestConnectorClient withLongRunningOperationRetryTimeout(int longRunningO * * @return the generateClientRequestId value. */ - public boolean generateClientRequestId() { + @Override + public boolean getGenerateClientRequestId() { return this.generateClientRequestId; } @@ -129,11 +131,10 @@ public boolean generateClientRequestId() { * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true. * * @param generateClientRequestId the generateClientRequestId value. - * @return the service client itself */ - public RestConnectorClient withGenerateClientRequestId(boolean generateClientRequestId) { + @Override + public void setGenerateClientRequestId(boolean generateClientRequestId) { this.generateClientRequestId = generateClientRequestId; - return this; } /** @@ -145,21 +146,22 @@ public RestConnectorClient withGenerateClientRequestId(boolean generateClientReq * Gets the Attachments object to access its operations. * @return the Attachments object. */ - public Attachments attachments() { + @Override + public Attachments getAttachments() { return this.attachments; } /** * The Conversations object to access its operations. */ - private RestConversations conversations; + private Conversations conversations; /** * Gets the Conversations object to access its operations. * @return the Conversations object. */ @Override - public RestConversations conversations() { + public Conversations getConversations() { return this.conversations; } @@ -227,16 +229,23 @@ protected void initialize() { */ @Override - public String userAgent() { + public String getUserAgent() { return this.user_agent_string; } + // this is to override the AzureServiceClient version + @Override + public String userAgent() { + return getUserAgent(); + } + /** * This is a copy of what the Azure Client does to create a RestClient. This returns * a RestClient.Builder so that the app can create a custom RestClient, and supply * it to ConnectorClient during construction. * - * One use case of this is for supplying a Proxy to the RestClient. + * One use case of this is for supplying a Proxy to the RestClient. Though it is + * recommended to set proxy information via the Java system properties. * * @param baseUrl * @param credentials diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java index ee25b26e6..1a0874227 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConversations.java @@ -16,8 +16,6 @@ import com.microsoft.rest.Validator; import java.io.IOException; import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import okhttp3.ResponseBody; import retrofit2.http.Body; @@ -108,15 +106,6 @@ interface ConversationsService { Observable> getConversationPagedMembers(@Path("conversationId") String conversationId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); } - public static CompletableFuture> completableFutureFromObservable(Observable observable) { - final CompletableFuture> future = new CompletableFuture<>(); - observable - .doOnError(future::completeExceptionally) - .toList() - .forEach(future::complete); - return future; - } - /** * Implementation of getConversations. * @@ -160,7 +149,7 @@ public ConversationsResult call(ServiceResponse response) { @Override public Observable> getConversationsWithServiceResponseAsync() { final String continuationToken = null; - return service.getConversations(continuationToken, this.client.acceptLanguage(), this.client.userAgent()) + return service.getConversations(continuationToken, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -216,7 +205,7 @@ public ConversationsResult call(ServiceResponse response) { */ @Override public Observable> getConversationsWithServiceResponseAsync(String continuationToken) { - return service.getConversations(continuationToken, this.client.acceptLanguage(), this.client.userAgent()) + return service.getConversations(continuationToken, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -272,15 +261,6 @@ public ConversationResourceResponse call(ServiceResponse> CreateConversationAsync(ConversationParameters parameters) { - CompletableFuture> future_result = completableFutureFromObservable(createConversationAsync(parameters)); - return future_result; - } - - /** * Implementation of createConversationWithServiceResponseAsync. * @@ -292,7 +272,7 @@ public Observable> createConversat throw new IllegalArgumentException("Parameter parameters is required and cannot be null."); } Validator.validate(parameters); - return service.createConversation(parameters, this.client.acceptLanguage(), this.client.userAgent()) + return service.createConversation(parameters, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -364,7 +344,7 @@ public Observable> sendToConversationWithServi throw new IllegalArgumentException("Parameter activity is required and cannot be null."); } Validator.validate(activity); - return service.sendToConversation(conversationId, activity, this.client.acceptLanguage(), this.client.userAgent()) + return service.sendToConversation(conversationId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -439,7 +419,7 @@ public Observable> updateActivityWithServiceRe throw new IllegalArgumentException("Parameter activity is required and cannot be null."); } Validator.validate(activity); - return service.updateActivity(conversationId, activityId, activity, this.client.acceptLanguage(), this.client.userAgent()) + return service.updateActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -514,7 +494,7 @@ public Observable> replyToActivityWithServiceR throw new IllegalArgumentException("Parameter activity is required and cannot be null."); } Validator.validate(activity); - return service.replyToActivity(conversationId, activityId, activity, this.client.acceptLanguage(), this.client.userAgent()) + return service.replyToActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -585,7 +565,7 @@ public Observable> deleteActivityWithServiceResponseAsync( if (activityId == null) { throw new IllegalArgumentException("Parameter activityId is required and cannot be null."); } - return service.deleteActivity(conversationId, activityId, this.client.acceptLanguage(), this.client.userAgent()) + return service.deleteActivity(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -652,7 +632,7 @@ public Observable>> getConversationMembersW if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } - return service.getConversationMembers(conversationId, this.client.acceptLanguage(), this.client.userAgent()) + return service.getConversationMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>>() { @Override public Observable>> call(Response response) { @@ -708,23 +688,6 @@ public Void call(ServiceResponse response) { }); } - /** - * DeleteConversationMemberFuture - * Deletes a member from a converstion. - This REST API takes a ConversationId and a memberId (of type string) and removes that member from the conversation. If that member was the last member - of the conversation, the conversation will also be deleted. - * - * @param conversationId Conversation ID - * @param memberId ID of the member to delete from this conversation - * @throws IllegalArgumentException thrown if parameters fail the validation - * @return CompletableFuture of List < Void > - */ - // FIXME: This return result is ridiculous. - public CompletableFuture> deleteConversationMemberFuture(String conversationId, String memberId) throws ExecutionException, InterruptedException { - CompletableFuture> future_result = completableFutureFromObservable(deleteConversationMemberAsync(conversationId, memberId)); - return future_result; - } - /** * Implementation of deleteConversationMemberWithServiceResponseAsync. * @@ -738,7 +701,7 @@ public Observable> deleteConversationMemberWithServiceResp if (memberId == null) { throw new IllegalArgumentException("Parameter memberId is required and cannot be null."); } - return service.deleteConversationMember(conversationId, memberId, this.client.acceptLanguage(), this.client.userAgent()) + return service.deleteConversationMember(conversationId, memberId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -809,7 +772,7 @@ public Observable>> getActivityMembersWithS if (activityId == null) { throw new IllegalArgumentException("Parameter activityId is required and cannot be null."); } - return service.getActivityMembers(conversationId, activityId, this.client.acceptLanguage(), this.client.userAgent()) + return service.getActivityMembers(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>>() { @Override public Observable>> call(Response response) { @@ -879,7 +842,7 @@ public Observable> uploadAttachmentWithService throw new IllegalArgumentException("Parameter attachmentUpload is required and cannot be null."); } Validator.validate(attachmentUpload); - return service.uploadAttachment(conversationId, attachmentUpload, this.client.acceptLanguage(), this.client.userAgent()) + return service.uploadAttachment(conversationId, attachmentUpload, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -952,7 +915,7 @@ public Observable> sendConversationHistoryWith throw new IllegalArgumentException("Parameter history is required and cannot be null."); } Validator.validate(history); - return service.sendConversationHistory(conversationId, history, this.client.acceptLanguage(), this.client.userAgent()) + return service.sendConversationHistory(conversationId, history, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { @@ -1021,7 +984,7 @@ public Observable> getConversationPagedMembe if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } - return service.getConversationPagedMembers(conversationId, this.client.acceptLanguage(), this.client.userAgent()) + return service.getConversationPagedMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override public Observable> call(Response response) { diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java index cdb31963b..6b88f87d6 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/AttachmentsTest.java @@ -24,11 +24,11 @@ public void GetAttachmentInfo() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.getId(), attachment); + ResourceResponse attachmentResponse = connector.getConversations().uploadAttachment(conversation.getId(), attachment); - AttachmentInfo response = connector.attachments().getAttachmentInfo(attachmentResponse.getId()); + AttachmentInfo response = connector.getAttachments().getAttachmentInfo(attachmentResponse.getId()); Assert.assertEquals(attachment.getName(), response.getName()); } @@ -57,14 +57,14 @@ public void GetAttachment() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse attachmentResponse = connector.conversations().uploadAttachment(conversation.getId(), attachment); + ResourceResponse attachmentResponse = connector.getConversations().uploadAttachment(conversation.getId(), attachment); - AttachmentInfo attachmentInfo = connector.attachments().getAttachmentInfo(attachmentResponse.getId()); + AttachmentInfo attachmentInfo = connector.getAttachments().getAttachmentInfo(attachmentResponse.getId()); for (AttachmentView attView : attachmentInfo.getViews()) { - InputStream retrievedAttachment = connector.attachments().getAttachment(attachmentResponse.getId(), attView.getViewId()); + InputStream retrievedAttachment = connector.getAttachments().getAttachment(attachmentResponse.getId(), attView.getViewId()); Assert.assertTrue(isSame(retrievedAttachment, attachmentStream)); } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java index 3952f67df..8ca761caf 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/ConversationsTest.java @@ -31,7 +31,7 @@ public void CreateConversation() { setActivity(activity); }}; - ConversationResourceResponse result = connector.conversations().createConversation(params); + ConversationResourceResponse result = connector.getConversations().createConversation(params); Assert.assertNotNull(result.getActivityId()); } @@ -53,7 +53,7 @@ public void CreateConversationWithInvalidBot() { }}; try { - ConversationResourceResponse result = connector.conversations().createConversation(params); + ConversationResourceResponse result = connector.getConversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -77,7 +77,7 @@ public void CreateConversationWithoutMembers() { }}; try { - ConversationResourceResponse result = connector.conversations().createConversation(params); + ConversationResourceResponse result = connector.getConversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("BadArgument", e.body().getError().getCode().toString()); @@ -101,7 +101,7 @@ public void CreateConversationWithBotMember() { }}; try { - ConversationResourceResponse result = connector.conversations().createConversation(params); + ConversationResourceResponse result = connector.getConversations().createConversation(params); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("BadArgument", e.body().getError().getCode().toString()); @@ -116,9 +116,9 @@ public void GetConversationMembers() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - List members = connector.conversations().getConversationMembers(conversation.getId()); + List members = connector.getConversations().getConversationMembers(conversation.getId()); boolean hasUser = false; @@ -138,10 +138,10 @@ public void GetConversationMembersWithInvalidConversationId() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); try { - List members = connector.conversations().getConversationMembers(conversation.getId().concat("M")); + List members = connector.getConversations().getConversationMembers(conversation.getId().concat("M")); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -156,10 +156,10 @@ public void GetConversationPagedMembers() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); try { - PagedMembersResult pagedMembers = connector.conversations().getConversationPagedMembers(conversation.getId()); + PagedMembersResult pagedMembers = connector.getConversations().getConversationPagedMembers(conversation.getId()); boolean hasUser = false; for (ChannelAccount member : pagedMembers.getMembers()) { @@ -189,9 +189,9 @@ public void SendToConversation() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); Assert.assertNotNull(response.getId()); } @@ -211,10 +211,10 @@ public void SendToConversationWithInvalidConversationId() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); try { - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId().concat("M"), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId().concat("M"), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -230,7 +230,7 @@ public void SendToConversationWithInvalidBotId() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); bot.setId("B21S8SG7K:T03CWQ0QB"); Activity activity = new Activity(ActivityTypes.MESSAGE) {{ @@ -241,7 +241,7 @@ public void SendToConversationWithInvalidBotId() { }}; try { - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("MissingProperty", e.body().getError().getCode().toString()); @@ -286,9 +286,9 @@ public void SendCardToConversation() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); Assert.assertNotNull(response.getId()); } @@ -308,9 +308,9 @@ public void GetActivityMembers() { setActivity(activity); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - List members = connector.conversations().getActivityMembers(conversation.getId(), conversation.getActivityId()); + List members = connector.getConversations().getActivityMembers(conversation.getId(), conversation.getActivityId()); boolean hasUser = false; @@ -337,10 +337,10 @@ public void GetActivityMembersWithInvalidConversationId() { setActivity(activity); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); try { - List members = connector.conversations().getActivityMembers(conversation.getId().concat("M"), conversation.getActivityId()); + List members = connector.getConversations().getActivityMembers(conversation.getId().concat("M"), conversation.getActivityId()); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -368,11 +368,11 @@ public void ReplyToActivity() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); - ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.getId(), response.getId(), reply); + ResourceResponse replyResponse = connector.getConversations().replyToActivity(conversation.getId(), response.getId(), reply); Assert.assertNotNull(replyResponse.getId()); } @@ -397,12 +397,12 @@ public void ReplyToActivityWithInvalidConversationId() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); try { - ResourceResponse replyResponse = connector.conversations().replyToActivity(conversation.getId().concat("M"), response.getId(), reply); + ResourceResponse replyResponse = connector.getConversations().replyToActivity(conversation.getId().concat("M"), response.getId(), reply); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -425,9 +425,9 @@ public void DeleteActivity() { setActivity(activity); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - connector.conversations().deleteActivity(conversation.getId(), conversation.getActivityId()); + connector.getConversations().deleteActivity(conversation.getId(), conversation.getActivityId()); Assert.assertNotNull(conversation.getActivityId()); } @@ -447,10 +447,10 @@ public void DeleteActivityWithInvalidConversationId() { setActivity(activity); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); try { - connector.conversations().deleteActivity("B21S8SG7K:T03CWQ0QB", conversation.getActivityId()); + connector.getConversations().deleteActivity("B21S8SG7K:T03CWQ0QB", conversation.getActivityId()); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -472,14 +472,14 @@ public void UpdateActivity() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); activity.setId(response.getId()); activity.setText("TEST Update Activity"); - ResourceResponse updateResponse = connector.conversations().updateActivity(conversation.getId(), response.getId(), activity); + ResourceResponse updateResponse = connector.getConversations().updateActivity(conversation.getId(), response.getId(), activity); Assert.assertNotNull(updateResponse.getId()); } @@ -498,15 +498,15 @@ public void UpdateActivityWithInvalidConversationId() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().sendToConversation(conversation.getId(), activity); + ResourceResponse response = connector.getConversations().sendToConversation(conversation.getId(), activity); activity.setId(response.getId()); activity.setText("TEST Update Activity"); try { - ResourceResponse updateResponse = connector.conversations().updateActivity("B21S8SG7K:T03CWQ0QB", response.getId(), activity); + ResourceResponse updateResponse = connector.getConversations().updateActivity("B21S8SG7K:T03CWQ0QB", response.getId(), activity); Assert.fail("expected exception was not occurred."); } catch (ErrorResponseException e) { Assert.assertEquals("ServiceError", e.body().getError().getCode().toString()); @@ -528,9 +528,9 @@ public void UploadAttachment() { setBot(bot); }}; - ConversationResourceResponse conversation = connector.conversations().createConversation(createMessage); + ConversationResourceResponse conversation = connector.getConversations().createConversation(createMessage); - ResourceResponse response = connector.conversations().uploadAttachment(conversation.getId(), attachment); + ResourceResponse response = connector.getConversations().uploadAttachment(conversation.getId(), attachment); Assert.assertNotNull(response.getId()); } diff --git a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java index f5148deed..d2aebf011 100644 --- a/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java +++ b/samples/bot-connector-sample/src/main/java/com/microsoft/bot/connector/sample/App.java @@ -61,7 +61,7 @@ public void handle(HttpExchange httpExchange) throws IOException { if (activity.getType().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), this.credentials); - connector.conversations().sendToConversation( + connector.getConversations().sendToConversation( activity.getConversation().getId(), activity.createReply("Echo: " + activity.getText())); } diff --git a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java index afd9ed44f..7d34d05f9 100644 --- a/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java +++ b/samples/servlet-echo/src/main/java/com/microsoft/bot/sample/servlet/EchoServlet.java @@ -71,7 +71,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) if (activity.getType().equals(ActivityTypes.MESSAGE)) { // reply activity with the same text ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), this.credentials); - connector.conversations().sendToConversation( + connector.getConversations().sendToConversation( activity.getConversation().getId(), activity.createReply("Echo: " + activity.getText())); } diff --git a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java index 5d36e6740..b3cb4612f 100644 --- a/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java +++ b/samples/spring-echo/src/main/java/com/microsoft/bot/sample/spring/BotController.java @@ -71,7 +71,7 @@ public ResponseEntity incoming(@RequestBody Activity activity, // reply activity with the same text ConnectorClient connector = new RestConnectorClient(activity.getServiceUrl(), _credentials); - connector.conversations().sendToConversation( + connector.getConversations().sendToConversation( activity.getConversation().getId(), activity.createReply("Echo: " + activity.getText())); } From 58ee9bfe3ce5434353d91fae5a5d33747c9e229f Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 13:41:11 -0500 Subject: [PATCH 19/26] bot-connector linter corrections. --- .../microsoft/bot/connector/AsyncHelper.java | 23 + .../microsoft/bot/connector/Attachments.java | 6 +- .../bot/connector/ConnectorClient.java | 6 +- .../bot/connector/Conversations.java | 420 +++++++++------ .../bot/connector/ExecutorFactory.java | 10 +- .../microsoft/bot/connector/UserAgent.java | 3 +- .../authentication/AdalAuthenticator.java | 6 +- .../AuthenticationConstants.java | 9 +- .../authentication/ChannelValidation.java | 25 +- .../authentication/CredentialProvider.java | 31 ++ .../authentication/EmulatorValidation.java | 58 +- .../authentication/EndorsementsValidator.java | 3 +- .../EnterpriseChannelValidation.java | 38 +- .../GovernmentAuthenticationConstants.java | 9 +- .../GovernmentChannelValidation.java | 24 +- .../authentication/JwtTokenExtractor.java | 39 +- .../authentication/JwtTokenValidation.java | 49 +- .../MicrosoftAppCredentials.java | 9 +- .../authentication/OpenIdMetadata.java | 3 +- .../TokenValidationParameters.java | 14 +- .../bot/connector/rest/RestAttachments.java | 72 ++- .../connector/rest/RestConnectorClient.java | 8 +- .../bot/connector/rest/RestConversations.java | 500 +++++++++--------- 23 files changed, 832 insertions(+), 533 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java index eeaeedbcf..5eb56e3de 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/AsyncHelper.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.microsoft.bot.connector; import rx.Observable; @@ -6,6 +9,18 @@ import java.util.concurrent.CompletableFuture; public class AsyncHelper { + private AsyncHelper() { + } + + /** + * Creates a CompletableFuture from an RxJava Observable. + * + * Because Observables are n+, this results in a List return values. + * + * @param observable The Observable to convert. + * @param The return type of the Observable. + * @return A CompletableFuture of List. + */ public static CompletableFuture> completableFutureFromObservable(Observable observable) { final CompletableFuture> future = new CompletableFuture<>(); observable @@ -15,6 +30,14 @@ public static CompletableFuture> completableFutureFromObservable(Obs return future; } + /** + * Creates a CompletableFuture from an Rx Java Observable, enforcing a single + * result of type T. + * + * @param observable The Observable to convert. + * @param The returns type. + * @return A CompletableFutre of type T. + */ public static CompletableFuture completableSingleFutureFromObservable(Observable observable) { final CompletableFuture future = new CompletableFuture<>(); observable diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java index 63974dcab..d0bdf3c78 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Attachments.java @@ -39,7 +39,8 @@ public interface Attachments { * @return the {@link ServiceFuture} object * @throws IllegalArgumentException thrown if parameters fail the validation */ - ServiceFuture getAttachmentInfoAsync(String attachmentId, final ServiceCallback serviceCallback); + ServiceFuture getAttachmentInfoAsync(String attachmentId, + final ServiceCallback serviceCallback); /** * GetAttachmentInfo. @@ -83,7 +84,8 @@ public interface Attachments { * @return the {@link ServiceFuture} object * @throws IllegalArgumentException thrown if parameters fail the validation */ - ServiceFuture getAttachmentAsync(String attachmentId, String viewId, final ServiceCallback serviceCallback); + ServiceFuture getAttachmentAsync(String attachmentId, String viewId, + final ServiceCallback serviceCallback); /** * GetAttachment. diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java index a2f64abb0..3d83f7f39 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorClient.java @@ -67,14 +67,16 @@ public interface ConnectorClient { void setLongRunningOperationRetryTimeout(int longRunningOperationRetryTimeout); /** - * Gets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.. + * Gets When set to true a unique x-ms-client-request-id value is generated and included in each request. + * is true. * * @return the generateClientRequestId value. */ boolean getGenerateClientRequestId(); /** - * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. Default is true.. + * Sets When set to true a unique x-ms-client-request-id value is generated and included in each request. + * Default is true. * * @param generateClientRequestId the generateClientRequestId value. * @return the service client itself diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java index 547ac65cd..53f043e51 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/Conversations.java @@ -26,10 +26,13 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with + * the returned token to get more values. + * + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @throws IllegalArgumentException thrown if parameters fail the validation * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent @@ -40,24 +43,30 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with + * the returned token to get more values. + * + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture getConversationsAsync(final ServiceCallback serviceCallback); + ServiceFuture getConversationsAsync(ServiceCallback serviceCallback); /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ConversationsResult object @@ -67,10 +76,13 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ConversationsResult object @@ -80,10 +92,13 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @param continuationToken skip or continuation token * @throws IllegalArgumentException thrown if parameters fail the validation @@ -95,25 +110,30 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @param continuationToken skip or continuation token * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture getConversationsAsync(String continuationToken, final ServiceCallback serviceCallback); + ServiceFuture getConversationsAsync( + String continuationToken, ServiceCallback serviceCallback); /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @param continuationToken skip or continuation token * @throws IllegalArgumentException thrown if parameters fail the validation @@ -124,10 +144,12 @@ public interface Conversations { /** * GetConversations. * List the Conversations in which this bot has participated. - GET from this method with a skip token - The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. If the skip token is not empty, then - there are further values to be returned. Call this method again with the returned token to get more values. - Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that describe the members of the conversation. + * GET from this method with a skip token + * The return value is a ConversationsResult, which contains an array of ConversationMembers and a skip token. + * If the skip token is not empty, then there are further values to be returned. Call this method again with the + * returned token to get more values. + * Each ConversationMembers object contains the ID of the conversation and an array of ChannelAccounts that + * describe the members of the conversation. * * @param continuationToken skip or continuation token * @throws IllegalArgumentException thrown if parameters fail the validation @@ -138,17 +160,19 @@ public interface Conversations { /** * CreateConversation. * Create a new Conversation. - POST to this method with a + * POST to this method with a * Bot being the bot creating the conversation * IsGroup set to true if this is not a direct message (default is false) * Members array contining the members you want to have be in the conversation. - The return value is a ResourceResponse which contains a conversation id which is suitable for use - in the message payload and REST API uris. - Most channels only support the semantics of bots initiating a direct message conversation. An example of how to do that would be: - ``` - var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, members = new ChannelAccount[] { new ChannelAccount("user1") } ); - await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; - ```. + * The return value is a ResourceResponse which contains a conversation id which is suitable for use in the + * message payload and REST API uris. + * Most channels only support the semantics of bots initiating a direct message conversation. An example of how + * to do that would be: + * ``` + * var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, + * members = new ChannelAccount[] { new ChannelAccount("user1") } ); + * await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; + * ```. * * @param parameters Parameters to create the conversation from * @throws IllegalArgumentException thrown if parameters fail the validation @@ -160,39 +184,44 @@ public interface Conversations { /** * CreateConversation. * Create a new Conversation. - POST to this method with a + * POST to this method with a * Bot being the bot creating the conversation * IsGroup set to true if this is not a direct message (default is false) * Members array contining the members you want to have be in the conversation. - The return value is a ResourceResponse which contains a conversation id which is suitable for use - in the message payload and REST API uris. - Most channels only support the semantics of bots initiating a direct message conversation. An example of how to do that would be: - ``` - var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, members = new ChannelAccount[] { new ChannelAccount("user1") } ); - await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; - ```. + * The return value is a ResourceResponse which contains a conversation id which is suitable for use in the + * message payload and REST API uris. + * Most channels only support the semantics of bots initiating a direct message conversation. An example of how + * to do that would be: + * ``` + * var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, + * members = new ChannelAccount[] { new ChannelAccount("user1") } ); + * await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; + * ``` * * @param parameters Parameters to create the conversation from * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture createConversationAsync(ConversationParameters parameters, final ServiceCallback serviceCallback); + ServiceFuture createConversationAsync( + ConversationParameters parameters, ServiceCallback serviceCallback); /** * CreateConversation. * Create a new Conversation. - POST to this method with a + * POST to this method with a * Bot being the bot creating the conversation * IsGroup set to true if this is not a direct message (default is false) * Members array contining the members you want to have be in the conversation. - The return value is a ResourceResponse which contains a conversation id which is suitable for use - in the message payload and REST API uris. - Most channels only support the semantics of bots initiating a direct message conversation. An example of how to do that would be: - ``` - var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, members = new ChannelAccount[] { new ChannelAccount("user1") } ); - await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; - ```. + * The return value is a ResourceResponse which contains a conversation id which is suitable for use + * in the message payload and REST API uris. + * Most channels only support the semantics of bots initiating a direct message conversation. An example of how + * to do that would be: + * ``` + * var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, + * members = new ChannelAccount[] { new ChannelAccount("user1") } ); + * await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; + * ``` * * @param parameters Parameters to create the conversation from * @throws IllegalArgumentException thrown if parameters fail the validation @@ -203,32 +232,37 @@ public interface Conversations { /** * CreateConversation. * Create a new Conversation. - POST to this method with a + * POST to this method with a * Bot being the bot creating the conversation * IsGroup set to true if this is not a direct message (default is false) * Members array contining the members you want to have be in the conversation. - The return value is a ResourceResponse which contains a conversation id which is suitable for use - in the message payload and REST API uris. - Most channels only support the semantics of bots initiating a direct message conversation. An example of how to do that would be: - ``` - var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, members = new ChannelAccount[] { new ChannelAccount("user1") } ); - await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; - ```. + * The return value is a ResourceResponse which contains a conversation id which is suitable for use + * in the message payload and REST API uris. + * Most channels only support the semantics of bots initiating a direct message conversation. An example of how + * to do that would be: + * ``` + * var resource = await connector.conversations.CreateConversation(new ConversationParameters(){ Bot = bot, + * members = new ChannelAccount[] { new ChannelAccount("user1") } ); + * await connect.Conversations.SendToConversationAsync(resource.Id, new Activity() ... ) ; + * ```. * * @param parameters Parameters to create the conversation from * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ConversationResourceResponse object */ - Observable> createConversationWithServiceResponseAsync(ConversationParameters parameters); + Observable> createConversationWithServiceResponseAsync( + ConversationParameters parameters); /** * SendToConversation. * This method allows you to send an activity to the end of a conversation. - This is slightly different from ReplyToActivity(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from ReplyToActivity(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activity Activity to send @@ -241,11 +275,13 @@ This is slightly different from ReplyToActivity(). /** * SendToConversation. * This method allows you to send an activity to the end of a conversation. - This is slightly different from ReplyToActivity(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from ReplyToActivity(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activity Activity to send @@ -253,16 +289,19 @@ This is slightly different from ReplyToActivity(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture sendToConversationAsync(String conversationId, Activity activity, final ServiceCallback serviceCallback); + ServiceFuture sendToConversationAsync(String conversationId, Activity activity, + ServiceCallback serviceCallback); /** * SendToConversation. * This method allows you to send an activity to the end of a conversation. - This is slightly different from ReplyToActivity(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from ReplyToActivity(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activity Activity to send @@ -274,24 +313,27 @@ This is slightly different from ReplyToActivity(). /** * SendToConversation. * This method allows you to send an activity to the end of a conversation. - This is slightly different from ReplyToActivity(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from ReplyToActivity(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activity Activity to send * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ResourceResponse object */ - Observable> sendToConversationWithServiceResponseAsync(String conversationId, Activity activity); + Observable> sendToConversationWithServiceResponseAsync( + String conversationId, Activity activity); /** * UpdateActivity. * Edit an existing activity. - Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. - For example, you can remove buttons after someone has clicked "Approve" button. + * Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. + * For example, you can remove buttons after someone has clicked "Approve" button. * * @param conversationId Conversation ID * @param activityId activityId to update @@ -305,8 +347,8 @@ This is slightly different from ReplyToActivity(). /** * UpdateActivity. * Edit an existing activity. - Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. - For example, you can remove buttons after someone has clicked "Approve" button. + * Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. + * For example, you can remove buttons after someone has clicked "Approve" button. * * @param conversationId Conversation ID * @param activityId activityId to update @@ -315,13 +357,16 @@ This is slightly different from ReplyToActivity(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture updateActivityAsync(String conversationId, String activityId, Activity activity, final ServiceCallback serviceCallback); + ServiceFuture updateActivityAsync(String conversationId, + String activityId, + Activity activity, + ServiceCallback serviceCallback); /** * UpdateActivity. * Edit an existing activity. - Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. - For example, you can remove buttons after someone has clicked "Approve" button. + * Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. + * For example, you can remove buttons after someone has clicked "Approve" button. * * @param conversationId Conversation ID * @param activityId activityId to update @@ -334,8 +379,8 @@ This is slightly different from ReplyToActivity(). /** * UpdateActivity. * Edit an existing activity. - Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. - For example, you can remove buttons after someone has clicked "Approve" button. + * Some channels allow you to edit an existing activity to reflect the new state of a bot conversation. + * For example, you can remove buttons after someone has clicked "Approve" button. * * @param conversationId Conversation ID * @param activityId activityId to update @@ -343,16 +388,20 @@ This is slightly different from ReplyToActivity(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ResourceResponse object */ - Observable> updateActivityWithServiceResponseAsync(String conversationId, String activityId, Activity activity); + Observable> updateActivityWithServiceResponseAsync(String conversationId, + String activityId, + Activity activity); /** * ReplyToActivity. * This method allows you to reply to an activity. - This is slightly different from SendToConversation(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from SendToConversation(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activityId activityId the reply is to (OPTIONAL) @@ -366,11 +415,13 @@ This is slightly different from SendToConversation(). /** * ReplyToActivity. * This method allows you to reply to an activity. - This is slightly different from SendToConversation(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from SendToConversation(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activityId activityId the reply is to (OPTIONAL) @@ -379,16 +430,21 @@ This is slightly different from SendToConversation(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture replyToActivityAsync(String conversationId, String activityId, Activity activity, final ServiceCallback serviceCallback); + ServiceFuture replyToActivityAsync(String conversationId, + String activityId, + Activity activity, + ServiceCallback serviceCallback); /** * ReplyToActivity. * This method allows you to reply to an activity. - This is slightly different from SendToConversation(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from SendToConversation(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activityId activityId the reply is to (OPTIONAL) @@ -401,11 +457,13 @@ This is slightly different from SendToConversation(). /** * ReplyToActivity. * This method allows you to reply to an activity. - This is slightly different from SendToConversation(). - * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the timestamp or semantics of the channel. - * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. - Use ReplyToActivity when replying to a specific activity in the conversation. - Use SendToConversation in all other cases. + * This is slightly different from SendToConversation(). + * SendToConverstion(conversationId) - will append the activity to the end of the conversation according to the + * timestamp or semantics of the channel. + * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply to another activity, if the channel + * supports it. If the channel does not support nested replies, ReplyToActivity falls back to SendToConversation. + * Use ReplyToActivity when replying to a specific activity in the conversation. + * Use SendToConversation in all other cases. * * @param conversationId Conversation ID * @param activityId activityId the reply is to (OPTIONAL) @@ -413,12 +471,14 @@ This is slightly different from SendToConversation(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ResourceResponse object */ - Observable> replyToActivityWithServiceResponseAsync(String conversationId, String activityId, Activity activity); + Observable> replyToActivityWithServiceResponseAsync( + String conversationId, String activityId, Activity activity); /** * DeleteActivity. * Delete an existing activity. - Some channels allow you to delete an existing activity, and if successful this method will remove the specified activity. + * Some channels allow you to delete an existing activity, and if successful this method will remove the + * specified activity. * * @param conversationId Conversation ID * @param activityId activityId to delete @@ -430,7 +490,8 @@ This is slightly different from SendToConversation(). /** * DeleteActivity. * Delete an existing activity. - Some channels allow you to delete an existing activity, and if successful this method will remove the specified activity. + * Some channels allow you to delete an existing activity, and if successful this method will remove the + * specified activity. * * @param conversationId Conversation ID * @param activityId activityId to delete @@ -438,12 +499,15 @@ This is slightly different from SendToConversation(). * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture deleteActivityAsync(String conversationId, String activityId, final ServiceCallback serviceCallback); + ServiceFuture deleteActivityAsync(String conversationId, + String activityId, + ServiceCallback serviceCallback); /** * DeleteActivity. * Delete an existing activity. - Some channels allow you to delete an existing activity, and if successful this method will remove the specified activity. + * Some channels allow you to delete an existing activity, and if successful this method will remove the specified + * activity. * * @param conversationId Conversation ID * @param activityId activityId to delete @@ -455,7 +519,8 @@ This is slightly different from SendToConversation(). /** * DeleteActivity. * Delete an existing activity. - Some channels allow you to delete an existing activity, and if successful this method will remove the specified activity. + * Some channels allow you to delete an existing activity, and if successful this method will remove the specified + * activity. * * @param conversationId Conversation ID * @param activityId activityId to delete @@ -467,7 +532,8 @@ This is slightly different from SendToConversation(). /** * GetConversationMembers. * Enumerate the members of a converstion. - This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members of the conversation. + * This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members + * of the conversation. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation @@ -479,19 +545,22 @@ This is slightly different from SendToConversation(). /** * GetConversationMembers. * Enumerate the members of a converstion. - This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members of the conversation. + * This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members + * of the conversation. * * @param conversationId Conversation ID * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture> getConversationMembersAsync(String conversationId, final ServiceCallback> serviceCallback); + ServiceFuture> getConversationMembersAsync( + String conversationId, ServiceCallback> serviceCallback); /** * GetConversationMembers. * Enumerate the members of a converstion. - This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members of the conversation. + * This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members + * of the conversation. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation @@ -502,19 +571,21 @@ This is slightly different from SendToConversation(). /** * GetConversationMembers. * Enumerate the members of a conversation. - This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members of the conversation. + * This REST API takes a ConversationId and returns an array of ChannelAccount objects representing the members + * of the conversation. * * @param conversationId Conversation ID * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the List<ChannelAccount> object */ - Observable>> getConversationMembersWithServiceResponseAsync(String conversationId); + Observable>> getConversationMembersWithServiceResponseAsync( + String conversationId); /** * DeleteConversationMember. * Deletes a member from a conversation. - This REST API takes a ConversationId and a memberId (of type string) and removes that member from the conversation. If that member was the last member - of the conversation, the conversation will also be deleted. + * This REST API takes a ConversationId and a memberId (of type string) and removes that member from the + * conversation. If that member was the last member of the conversation, the conversation will also be deleted. * * @param conversationId Conversation ID * @param memberId ID of the member to delete from this conversation @@ -526,8 +597,9 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * DeleteConversationMember. * Deletes a member from a conversation. - This REST API takes a ConversationId and a memberId (of type string) and removes that member from the conversation. If that member was the last member - of the conversation, the conversation will also be deleted. + * This REST API takes a ConversationId and a memberId (of type string) and removes that member from the + * conversation. If that member was the last member + * of the conversation, the conversation will also be deleted. * * @param conversationId Conversation ID * @param memberId ID of the member to delete from this conversation @@ -535,13 +607,15 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture deleteConversationMemberAsync(String conversationId, String memberId, final ServiceCallback serviceCallback); + ServiceFuture deleteConversationMemberAsync(String conversationId, + String memberId, + ServiceCallback serviceCallback); /** * DeleteConversationMember. * Deletes a member from a conversation. - This REST API takes a ConversationId and a memberId (of type string) and removes that member from the conversation. If that member was the last member - of the conversation, the conversation will also be deleted. + * This REST API takes a ConversationId and a memberId (of type string) and removes that member from the + * conversation. If that member was the last member of the conversation, the conversation will also be deleted. * * @param conversationId Conversation ID * @param memberId ID of the member to delete from this conversation @@ -553,20 +627,22 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * DeleteConversationMember. * Deletes a member from a conversation. - This REST API takes a ConversationId and a memberId (of type string) and removes that member from the conversation. If that member was the last member - of the conversation, the conversation will also be deleted. + * This REST API takes a ConversationId and a memberId (of type string) and removes that member from the + * conversation. If that member was the last member of the conversation, the conversation will also be deleted. * * @param conversationId Conversation ID * @param memberId ID of the member to delete from this conversation * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceResponse} object if successful. */ - Observable> deleteConversationMemberWithServiceResponseAsync(String conversationId, String memberId); + Observable> deleteConversationMemberWithServiceResponseAsync( + String conversationId, String memberId); /** * GetActivityMembers. * Enumerate the members of an activity. - This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects representing the members of the particular activity in the conversation. + * This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects + * representing the members of the particular activity in the conversation. * * @param conversationId Conversation ID * @param activityId Activity ID @@ -579,7 +655,8 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * GetActivityMembers. * Enumerate the members of an activity. - This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects representing the members of the particular activity in the conversation. + * This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects + * representing the members of the particular activity in the conversation. * * @param conversationId Conversation ID * @param activityId Activity ID @@ -587,12 +664,14 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture> getActivityMembersAsync(String conversationId, String activityId, final ServiceCallback> serviceCallback); + ServiceFuture> getActivityMembersAsync( + String conversationId, String activityId, ServiceCallback> serviceCallback); /** * GetActivityMembers. * Enumerate the members of an activity. - This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects representing the members of the particular activity in the conversation. + * This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects + * representing the members of the particular activity in the conversation. * * @param conversationId Conversation ID * @param activityId Activity ID @@ -604,20 +683,23 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * GetActivityMembers. * Enumerate the members of an activity. - This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects representing the members of the particular activity in the conversation. + * This REST API takes a ConversationId and a ActivityId, returning an array of ChannelAccount objects + * representing the members of the particular activity in the conversation. * * @param conversationId Conversation ID * @param activityId Activity ID * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the List<ChannelAccount> object */ - Observable>> getActivityMembersWithServiceResponseAsync(String conversationId, String activityId); + Observable>> getActivityMembersWithServiceResponseAsync( + String conversationId, String activityId); /** * UploadAttachment. * Upload an attachment directly into a channel's blob storage. - This is useful because it allows you to store data in a compliant store when dealing with enterprises. - The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the attachments API. + * This is useful because it allows you to store data in a compliant store when dealing with enterprises. + * The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the + * attachments API. * * @param conversationId Conversation ID * @param attachmentUpload Attachment data @@ -630,8 +712,9 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * UploadAttachment. * Upload an attachment directly into a channel's blob storage. - This is useful because it allows you to store data in a compliant store when dealing with enterprises. - The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the attachments API. + * This is useful because it allows you to store data in a compliant store when dealing with enterprises. + * The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the + * attachments API. * * @param conversationId Conversation ID * @param attachmentUpload Attachment data @@ -639,13 +722,17 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - ServiceFuture uploadAttachmentAsync(String conversationId, AttachmentData attachmentUpload, final ServiceCallback serviceCallback); + ServiceFuture uploadAttachmentAsync( + String conversationId, + AttachmentData attachmentUpload, + ServiceCallback serviceCallback); /** * UploadAttachment. * Upload an attachment directly into a channel's blob storage. - This is useful because it allows you to store data in a compliant store when dealing with enterprises. - The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the attachments API. + * This is useful because it allows you to store data in a compliant store when dealing with enterprises. + * The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the + * attachments API. * * @param conversationId Conversation ID * @param attachmentUpload Attachment data @@ -657,15 +744,17 @@ This REST API takes a ConversationId and a memberId (of type string) and removes /** * UploadAttachment. * Upload an attachment directly into a channel's blob storage. - This is useful because it allows you to store data in a compliant store when dealing with enterprises. - The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the attachments API. + * This is useful because it allows you to store data in a compliant store when dealing with enterprises. + * The response is a ResourceResponse which contains an AttachmentId which is suitable for using with the + * attachments API. * * @param conversationId Conversation ID * @param attachmentUpload Attachment data * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the ResourceResponse object */ - Observable> uploadAttachmentWithServiceResponseAsync(String conversationId, AttachmentData attachmentUpload); + Observable> uploadAttachmentWithServiceResponseAsync( + String conversationId, AttachmentData attachmentUpload); /** @@ -697,7 +786,8 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ - ServiceFuture sendConversationHistoryAsync(String conversationId, Transcript history, final ServiceCallback serviceCallback); + ServiceFuture sendConversationHistoryAsync( + String conversationId, Transcript history, ServiceCallback serviceCallback); /** * This method allows you to upload the historic activities to the conversation. @@ -727,7 +817,8 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the ResourceResponse object if successful. */ - Observable> sendConversationHistoryWithServiceResponseAsync(String conversationId, Transcript history); + Observable> sendConversationHistoryWithServiceResponseAsync( + String conversationId, Transcript history); /** * Enumerate the members of a conversation one page at a time. @@ -772,7 +863,8 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the PagedMembersResult object if successful. */ - ServiceFuture getConversationPagedMembersAsync(String conversationId, final ServiceCallback serviceCallback); + ServiceFuture getConversationPagedMembersAsync( + String conversationId, ServiceCallback serviceCallback); /** * Enumerate the members of a conversation one page at a time. @@ -816,6 +908,6 @@ This REST API takes a ConversationId and a memberId (of type string) and removes * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent * @return the observable to the ResourceResponse object */ - Observable> getConversationPagedMembersWithServiceResponseAsync(String conversationId); - + Observable> getConversationPagedMembersWithServiceResponseAsync( + String conversationId); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java index 9783ffa43..c1365851c 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ExecutorFactory.java @@ -12,7 +12,11 @@ /** * Provides a common Executor for Future operations. */ -public class ExecutorFactory { +public final class ExecutorFactory { + private ExecutorFactory() { + + } + private static ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory() { @Override public ForkJoinWorkerThread newThread(ForkJoinPool pool) { @@ -28,6 +32,10 @@ public ForkJoinWorkerThread newThread(ForkJoinPool pool) { null, false); + /** + * Provides an SDK wide ExecutorService for async calls. + * @return An ExecutorService. + */ public static ExecutorService getExecutor() { return executor; } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java index efc985190..da084188a 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java @@ -23,7 +23,8 @@ public class UserAgent { String build_version; final Properties properties = new Properties(); try { - InputStream propStream = RestConnectorClient.class.getClassLoader().getResourceAsStream("project.properties"); + InputStream propStream = RestConnectorClient.class.getClassLoader() + .getResourceAsStream("project.properties"); properties.load(propStream); build_version = properties.getProperty("version"); } catch (IOException e) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java index 82c763a63..5ef77adf5 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java @@ -17,10 +17,12 @@ public class AdalAuthenticator { private OAuthConfiguration oAuthConfiguration; private ClientCredential clientCredential; - public AdalAuthenticator(ClientCredential clientCredential, OAuthConfiguration configurationOAuth) throws MalformedURLException { + public AdalAuthenticator(ClientCredential clientCredential, OAuthConfiguration configurationOAuth) + throws MalformedURLException { this.oAuthConfiguration = configurationOAuth; this.clientCredential = clientCredential; - this.context = new AuthenticationContext(configurationOAuth.authority(), false, ExecutorFactory.getExecutor()); + this.context = new AuthenticationContext(configurationOAuth.authority(), false, + ExecutorFactory.getExecutor()); } public Future acquireToken() { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java index f83fadbc4..5bc809423 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AuthenticationConstants.java @@ -33,17 +33,20 @@ public final class AuthenticationConstants { /** * TO BOT FROM CHANNEL: OpenID metadata document for tokens coming from MSA. */ - public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = "https://login.botframework.com/v1/.well-known/openidconfiguration"; + public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = + "https://login.botframework.com/v1/.well-known/openidconfiguration"; /** * TO BOT FROM EMULATOR: OpenID metadata document for tokens coming from MSA. */ - public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; + public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = + "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; /** * TO BOT FROM ENTERPRISE CHANNEL: OpenID metadata document for tokens coming from MSA. */ - public static final String TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT = "https://%s.enterprisechannel.botframework.com/v1/.well-known/openidconfiguration"; + public static final String TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT = + "https://%s.enterprisechannel.botframework.com/v1/.well-known/openidconfiguration"; /** * Allowed token signing algorithms. Tokens come from channels to the bot. The code diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java index 5e17c8d95..6e564d5ef 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/ChannelValidation.java @@ -36,7 +36,8 @@ public class ChannelValidation { * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId) { + public static CompletableFuture authenticateToken( + String authHeader, CredentialProvider credentials, String channelId) { return authenticateToken(authHeader, credentials, channelId, new AuthenticationConfiguration()); } @@ -52,7 +53,8 @@ public static CompletableFuture authenticateToken(String authHea * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken( + String authHeader, CredentialProvider credentials, String channelId, AuthenticationConfiguration authConfig) { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( TOKENVALIDATIONPARAMETERS, AuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, @@ -89,7 +91,8 @@ public static CompletableFuture authenticateToken(String authHea } if (!credentials.isValidAppIdAsync(appIdFromAudienceClaim).join()) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); + throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", + appIdFromAudienceClaim)); } return identity; @@ -108,7 +111,8 @@ public static CompletableFuture authenticateToken(String authHea * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) { + public static CompletableFuture authenticateToken( + String authHeader, CredentialProvider credentials, String channelId, String serviceUrl) { return authenticateToken(authHeader, credentials, channelId, serviceUrl, new AuthenticationConfiguration()); } @@ -125,17 +129,24 @@ public static CompletableFuture authenticateToken(String authHea * On join: * @throws AuthenticationException A token issued by the Bot Framework emulator will FAIL this check. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + String channelId, + String serviceUrl, + AuthenticationConfiguration authConfig) { return ChannelValidation.authenticateToken(authHeader, credentials, channelId, authConfig) .thenApply(identity -> { if (!identity.claims().containsKey(AuthenticationConstants.SERVICE_URL_CLAIM)) { // Claim must be present. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Channel Token.", AuthenticationConstants.SERVICE_URL_CLAIM)); + throw new AuthenticationException(String.format("'%s' claim is required on Channel Token.", + AuthenticationConstants.SERVICE_URL_CLAIM)); } if (!serviceUrl.equalsIgnoreCase(identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM))) { // Claim must match. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim does not match service url provided (%s).", AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl)); + throw new AuthenticationException( + String.format("'%s' claim does not match service url provided (%s).", + AuthenticationConstants.SERVICE_URL_CLAIM, serviceUrl)); } return identity; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProvider.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProvider.java index 61b60976f..7c073e933 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProvider.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialProvider.java @@ -5,8 +5,39 @@ import java.util.concurrent.CompletableFuture; +/** + * CredentialProvider interface. This interface allows Bots to provide their own implementation of what is, + * and what is not, a valid appId and password. This is useful in the case of multi-tenant bots, where the + * bot may need to call out to a service to determine if a particular appid/password pair is valid. + * + * For Single Tenant bots (the vast majority) the simple static providers are sufficient. + */ public interface CredentialProvider { + /** + * Validates an app ID. + * + * @param appId The app ID to validate. + * @return A task that represents the work queued to execute. If the task is successful, the result is + * true if appId is valid for the controller; otherwise, false. + */ CompletableFuture isValidAppIdAsync(String appId); + + /** + * Gets the app password for a given bot app ID. + * + * @param appId The ID of the app to get the password for. + * @return A task that represents the work queued to execute. If the task is successful and the app ID is valid, + * the result contains the password; otherwise, null. This method is async to enable custom implementations + * that may need to call out to serviced to validate the appId / password pair. + */ CompletableFuture getAppPasswordAsync(String appId); + + /** + * Checks whether bot authentication is disabled. + * + * @return A task that represents the work queued to execute. If the task is successful and bot authentication + * is disabled, the result is true; otherwise, false. This method is async to enable custom implementations + * that may need to call out to serviced to validate the appId / password pair. + */ CompletableFuture isAuthenticationDisabledAsync(); } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java index 93ad9f9d5..1929d22a0 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EmulatorValidation.java @@ -20,20 +20,20 @@ public class EmulatorValidation { * TO BOT FROM EMULATOR: Token validation parameters when connecting to a channel. */ private static final TokenValidationParameters TOKENVALIDATIONPARAMETERS = new TokenValidationParameters() {{ - this.validateIssuer = true; - this.validIssuers = new ArrayList() {{ - add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); // Auth v3.1, 1.0 token - add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); // Auth v3.1, 2.0 token - add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); // Auth v3.2, 1.0 token - add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); // Auth v3.2, 2.0 token - add("https://sts.windows.net/cab8a31a-1906-4287-a0d8-4eef66b95f6e/"); // Auth for US Gov, 1.0 token - add("https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0"); // Auth for US Gov, 2.0 token - }}; - this.validateAudience = false; - this.validateLifetime = true; - this.clockSkew = Duration.ofMinutes(5); - this.requireSignedTokens = true; + this.validateIssuer = true; + this.validIssuers = new ArrayList() {{ + add("https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/"); // Auth v3.1, 1.0 + add("https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0"); // Auth v3.1, 2.0 + add("https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/"); // Auth v3.2, 1.0 + add("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0"); // Auth v3.2, 2.0 + add("https://sts.windows.net/cab8a31a-1906-4287-a0d8-4eef66b95f6e/"); // Auth for US Gov, 1.0 + add("https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0"); // Auth for US Gov, 2.0 }}; + this.validateAudience = false; + this.validateLifetime = true; + this.clockSkew = Duration.ofMinutes(5); + this.requireSignedTokens = true; + }}; /** * Determines if a given Auth header is from the Bot Framework Emulator @@ -92,9 +92,11 @@ public static Boolean isTokenFromEmulator(String authHeader) { * @return A valid ClaimsIdentity. *

* On join: - * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator + * tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId) { + public static CompletableFuture authenticateToken( + String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId) { return authenticateToken(authHeader, credentials, channelProvider, channelId, new AuthenticationConfiguration()); } @@ -110,9 +112,14 @@ public static CompletableFuture authenticateToken(String authHea * @return A valid ClaimsIdentity. *

* On join: - * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator + * tokens will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + String channelId, + AuthenticationConfiguration authConfig) { String openIdMetadataUrl = channelProvider != null && channelProvider.isGovernment() ? GovernmentAuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL : AuthenticationConstants.TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL; @@ -139,7 +146,8 @@ public static CompletableFuture authenticateToken(String authHea // comes from developer code that may be reaching out to a service, hence the // Async validation. if (!identity.claims().containsKey(AuthenticationConstants.VERSION_CLAIM)) { - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Tokens.", AuthenticationConstants.VERSION_CLAIM)); + throw new AuthenticationException(String.format("'%s' claim is required on Emulator Tokens.", + AuthenticationConstants.VERSION_CLAIM)); } String tokenVersion = identity.claims().get(AuthenticationConstants.VERSION_CLAIM); @@ -152,7 +160,9 @@ public static CompletableFuture authenticateToken(String authHea // the claim in the "appid" claim. if (!identity.claims().containsKey(AuthenticationConstants.APPID_CLAIM)) { // No claim around AppID. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '1.0'.", AuthenticationConstants.APPID_CLAIM)); + throw new AuthenticationException( + String.format("'%s' claim is required on Emulator Token version '1.0'.", + AuthenticationConstants.APPID_CLAIM)); } appId = identity.claims().get(AuthenticationConstants.APPID_CLAIM); @@ -160,17 +170,21 @@ public static CompletableFuture authenticateToken(String authHea // Emulator, "2.0" puts the AppId in the "azp" claim. if (!identity.claims().containsKey(AuthenticationConstants.AUTHORIZED_PARTY)) { // No claim around AppID. Not Authorized. - throw new AuthenticationException(String.format("'%s' claim is required on Emulator Token version '2.0'.", AuthenticationConstants.AUTHORIZED_PARTY)); + throw new AuthenticationException( + String.format("'%s' claim is required on Emulator Token version '2.0'.", + AuthenticationConstants.AUTHORIZED_PARTY)); } appId = identity.claims().get(AuthenticationConstants.AUTHORIZED_PARTY); } else { // Unknown Version. Not Authorized. - throw new AuthenticationException(String.format("Unknown Emulator Token version '%s'.", tokenVersion)); + throw new AuthenticationException( + String.format("Unknown Emulator Token version '%s'.", tokenVersion)); } if (!credentials.isValidAppIdAsync(appId).join()) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appId)); + throw new AuthenticationException( + String.format("Invalid AppId passed on token: '%s'.", appId)); } return identity; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java index f1b6b0288..b4c79f44b 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EndorsementsValidator.java @@ -17,7 +17,8 @@ public abstract class EndorsementsValidator { * @param channelId The channel name, typically extracted from the activity.ChannelId field, that * to which the Activity is affinitized. * @param endorsements Whoever signed the JWT token is permitted to send activities only for - * some specific channels. That list is the endorsement list, and is validated here against the channelId. + * some specific channels. That list is the endorsement list, and is validated here against + * the channelId. * @return True is the channelId is found in the Endorsement set. False if the channelId is not found. */ public static boolean validate(String channelId, List endorsements) { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java index 265401525..ca54d0faa 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/EnterpriseChannelValidation.java @@ -34,10 +34,16 @@ public class EnterpriseChannelValidation { * @return A valid ClaimsIdentity. * * On join: - * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens + * will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId) { - return authenticateToken(authHeader, credentials, channelProvider, serviceUrl, channelId, new AuthenticationConfiguration()); + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + String serviceUrl, + String channelId) { + return authenticateToken( + authHeader, credentials, channelProvider, serviceUrl, channelId, new AuthenticationConfiguration()); } /** @@ -52,9 +58,15 @@ public static CompletableFuture authenticateToken(String authHea * @return A valid ClaimsIdentity. * * On join: - * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens will pass. + * @throws AuthenticationException A token issued by the Bot Framework will FAIL this check. Only Emulator tokens + * will pass. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + String serviceUrl, + String channelId, + AuthenticationConfiguration authConfig) { if (authConfig == null) { throw new IllegalArgumentException("Missing AuthenticationConfiguration"); } @@ -64,7 +76,8 @@ public static CompletableFuture authenticateToken(String authHea .thenCompose(channelService -> { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( TOKENVALIDATIONPARAMETERS, - String.format(AuthenticationConstants.TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT, channelService), + String.format(AuthenticationConstants.TO_BOT_FROM_ENTERPRISE_CHANNEL_OPENID_METADATA_URL_FORMAT, + channelService), AuthenticationConstants.AllowedSigningAlgorithms); return tokenExtractor.getIdentityAsync(authHeader, channelId, authConfig.requiredEndorsements()); @@ -80,7 +93,9 @@ public static CompletableFuture authenticateToken(String authHea }); } - public static CompletableFuture validateIdentity(ClaimsIdentity identity, CredentialProvider credentials, String serviceUrl) { + public static CompletableFuture validateIdentity(ClaimsIdentity identity, + CredentialProvider credentials, + String serviceUrl) { return CompletableFuture.supplyAsync(() -> { if (identity == null || !identity.isAuthenticated()) { throw new AuthenticationException("Invalid Identity"); @@ -105,16 +120,19 @@ public static CompletableFuture validateIdentity(ClaimsIdentity boolean isValid = credentials.isValidAppIdAsync(appIdFromAudienceClaim).join(); if (!isValid) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); + throw new AuthenticationException( + String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); } String serviceUrlClaim = identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); if (StringUtils.isEmpty(serviceUrl)) { - throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); + throw new AuthenticationException( + String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); } if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { - throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); + throw new AuthenticationException( + String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); } return identity; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java index 9608f98be..12bce112e 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentAuthenticationConstants.java @@ -13,7 +13,8 @@ public class GovernmentAuthenticationConstants { /** * TO GOVERNMENT CHANNEL FROM BOT: Login URL. */ - public static final String TO_CHANNEL_FROM_BOT_LOGIN_URL = "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e"; + public static final String TO_CHANNEL_FROM_BOT_LOGIN_URL = + "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e"; /** * TO GOVERNMENT CHANNEL FROM BOT: OAuth scope to request. @@ -33,11 +34,13 @@ public class GovernmentAuthenticationConstants { /** * TO BOT FROM GOVERNMANT CHANNEL: OpenID metadata document for tokens coming from MSA. */ - public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = "https://login.botframework.azure.us/v1/.well-known/openidconfiguration"; + public static final String TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL = + "https://login.botframework.azure.us/v1/.well-known/openidconfiguration"; /** * TO BOT FROM GOVERNMENT EMULATOR: OpenID metadata document for tokens coming from MSA. */ - public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0/.well-known/openid-configuration"; + public static final String TO_BOT_FROM_EMULATOR_OPENID_METADATA_URL = + "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0/.well-known/openid-configuration"; } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java index af5494e48..fa78e3efe 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/GovernmentChannelValidation.java @@ -38,7 +38,10 @@ public class GovernmentChannelValidation { * On join: * @throws AuthenticationException Authentication failed. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId) { + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + String serviceUrl, + String channelId) { return authenticateToken(authHeader, credentials, serviceUrl, channelId, new AuthenticationConfiguration()); } @@ -55,7 +58,11 @@ public static CompletableFuture authenticateToken(String authHea * On join: * @throws AuthenticationException Authentication failed. */ - public static CompletableFuture authenticateToken(String authHeader, CredentialProvider credentials, String serviceUrl, String channelId, AuthenticationConfiguration authConfig) { + public static CompletableFuture authenticateToken(String authHeader, + CredentialProvider credentials, + String serviceUrl, + String channelId, + AuthenticationConfiguration authConfig) { JwtTokenExtractor tokenExtractor = new JwtTokenExtractor( TOKENVALIDATIONPARAMETERS, GovernmentAuthenticationConstants.TO_BOT_FROM_CHANNEL_OPENID_METADATA_URL, @@ -78,7 +85,9 @@ public static CompletableFuture authenticateToken(String authHea * On join: * @throws AuthenticationException Validation failed. */ - public static CompletableFuture validateIdentity(ClaimsIdentity identity, CredentialProvider credentials, String serviceUrl) { + public static CompletableFuture validateIdentity(ClaimsIdentity identity, + CredentialProvider credentials, + String serviceUrl) { return CompletableFuture.supplyAsync(() -> { if (identity == null || !identity.isAuthenticated()) { @@ -104,16 +113,19 @@ public static CompletableFuture validateIdentity(ClaimsIdentity boolean isValid = credentials.isValidAppIdAsync(appIdFromAudienceClaim).join(); if (!isValid) { - throw new AuthenticationException(String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); + throw new AuthenticationException( + String.format("Invalid AppId passed on token: '%s'.", appIdFromAudienceClaim)); } String serviceUrlClaim = identity.claims().get(AuthenticationConstants.SERVICE_URL_CLAIM); if (StringUtils.isEmpty(serviceUrl)) { - throw new AuthenticationException(String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); + throw new AuthenticationException( + String.format("Invalid serviceurl passed on token: '%s'.", serviceUrlClaim)); } if (!StringUtils.equals(serviceUrl, serviceUrlClaim)) { - throw new AuthenticationException(String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); + throw new AuthenticationException( + String.format("serviceurl doesn't match claim: '%s'.", serviceUrlClaim)); } return identity; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java index b37b905ba..6033377e1 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenExtractor.java @@ -29,7 +29,10 @@ public class JwtTokenExtractor { private List allowedSigningAlgorithms; private OpenIdMetadata openIdMetadata; - public JwtTokenExtractor(TokenValidationParameters tokenValidationParameters, String metadataUrl, List allowedSigningAlgorithms) { + public JwtTokenExtractor(TokenValidationParameters tokenValidationParameters, + String metadataUrl, + List allowedSigningAlgorithms) { + this.tokenValidationParameters = new TokenValidationParameters(tokenValidationParameters); this.tokenValidationParameters.requireSignedTokens = true; this.allowedSigningAlgorithms = allowedSigningAlgorithms; @@ -40,7 +43,9 @@ public CompletableFuture getIdentityAsync(String authorizationHe return getIdentityAsync(authorizationHeader, channelId, new ArrayList<>()); } - public CompletableFuture getIdentityAsync(String authorizationHeader, String channelId, List requiredEndorsements) { + public CompletableFuture getIdentityAsync(String authorizationHeader, + String channelId, + List requiredEndorsements) { if (authorizationHeader == null) { throw new IllegalArgumentException("authorizationHeader is required"); } @@ -53,7 +58,10 @@ public CompletableFuture getIdentityAsync(String authorizationHe return CompletableFuture.completedFuture(null); } - public CompletableFuture getIdentityAsync(String schema, String token, String channelId, List requiredEndorsements) { + public CompletableFuture getIdentityAsync(String schema, + String token, + String channelId, + List requiredEndorsements) { // No header in correct scheme or no token if (!schema.equalsIgnoreCase("bearer") || token == null) { return CompletableFuture.completedFuture(null); @@ -69,11 +77,14 @@ public CompletableFuture getIdentityAsync(String schema, String private boolean hasAllowedIssuer(String token) { DecodedJWT decodedJWT = JWT.decode(token); - return this.tokenValidationParameters.validIssuers != null && this.tokenValidationParameters.validIssuers.contains(decodedJWT.getIssuer()); + return this.tokenValidationParameters.validIssuers != null + && this.tokenValidationParameters.validIssuers.contains(decodedJWT.getIssuer()); } @SuppressWarnings("unchecked") - private CompletableFuture validateTokenAsync(String token, String channelId, List requiredEndorsements) { + private CompletableFuture validateTokenAsync(String token, + String channelId, + List requiredEndorsements) { DecodedJWT decodedJWT = JWT.decode(token); OpenIdMetadataKey key = this.openIdMetadata.getKey(decodedJWT.getKeyId()); @@ -93,19 +104,27 @@ private CompletableFuture validateTokenAsync(String token, Strin // needs to be matched by an endorsement. boolean isEndorsed = EndorsementsValidator.validate(channelId, key.endorsements); if (!isEndorsed) { - throw new AuthenticationException(String.format("Could not validate endorsement for key: %s with endorsements: %s", key.key.toString(), StringUtils.join(key.endorsements))); + throw new AuthenticationException( + String.format("Could not validate endorsement for key: %s with endorsements: %s", + key.key.toString(), StringUtils.join(key.endorsements))); } - // Verify that additional endorsements are satisfied. If no additional endorsements are expected, the requirement is satisfied as well + // Verify that additional endorsements are satisfied. If no additional endorsements are expected, + // the requirement is satisfied as well boolean additionalEndorsementsSatisfied = - requiredEndorsements.stream().allMatch((endorsement) -> EndorsementsValidator.validate(endorsement, key.endorsements)); + requiredEndorsements.stream(). + allMatch((endorsement) -> EndorsementsValidator.validate(endorsement, key.endorsements)); if (!additionalEndorsementsSatisfied) { - throw new AuthenticationException(String.format("Could not validate additional endorsement for key: %s with endorsements: %s", key.key.toString(), StringUtils.join(requiredEndorsements))); + throw new AuthenticationException( + String.format("Could not validate additional endorsement for key: %s with endorsements: %s", + key.key.toString(), StringUtils.join(requiredEndorsements))); } } if (!this.allowedSigningAlgorithms.contains(decodedJWT.getAlgorithm())) { - throw new AuthenticationException(String.format("Could not validate algorithm for key: %s with algorithms: %s", decodedJWT.getAlgorithm(), StringUtils.join(allowedSigningAlgorithms))); + throw new AuthenticationException( + String.format("Could not validate algorithm for key: %s with algorithms: %s", + decodedJWT.getAlgorithm(), StringUtils.join(allowedSigningAlgorithms))); } return new ClaimsIdentity(decodedJWT); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java index d7e185c06..8eb31a6ae 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/JwtTokenValidation.java @@ -9,7 +9,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; /** * Contains helper methods for authenticating incoming HTTP requests. @@ -25,8 +24,12 @@ public class JwtTokenValidation { * @return A task that represents the work queued to execute. * @throws AuthenticationException Throws on auth failed. */ - public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials, ChannelProvider channelProvider) throws AuthenticationException, InterruptedException, ExecutionException { - return authenticateRequest(activity, authHeader, credentials, channelProvider, new AuthenticationConfiguration()); + public static CompletableFuture authenticateRequest(Activity activity, + String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider) { + return authenticateRequest( + activity, authHeader, credentials, channelProvider, new AuthenticationConfiguration()); } /** @@ -39,7 +42,11 @@ public static CompletableFuture authenticateRequest(Activity act * @return A task that represents the work queued to execute. * @throws AuthenticationException Throws on auth failed. */ - public static CompletableFuture authenticateRequest(Activity activity, String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, AuthenticationConfiguration authConfig) throws AuthenticationException, InterruptedException, ExecutionException { + public static CompletableFuture authenticateRequest(Activity activity, + String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + AuthenticationConfiguration authConfig) { return CompletableFuture.supplyAsync(() -> { if (StringUtils.isEmpty(authHeader)) { // No auth header was sent. We might be on the anonymous code path. @@ -57,7 +64,14 @@ public static CompletableFuture authenticateRequest(Activity act // Go through the standard authentication path. This will throw AuthenticationException if // it fails. - ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader(authHeader, credentials, channelProvider, activity.getChannelId(), activity.getServiceUrl(), authConfig).join(); + ClaimsIdentity identity = JwtTokenValidation.validateAuthHeader( + authHeader, + credentials, + channelProvider, + activity.getChannelId(), + activity.getServiceUrl(), + authConfig) + .join(); // On the standard Auth path, we need to trust the URL that was incoming. MicrosoftAppCredentials.trustServiceUrl(activity.getServiceUrl()); @@ -82,8 +96,13 @@ public static CompletableFuture authenticateRequest(Activity act * On join: * @throws AuthenticationException Authentication Error */ - public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl) { - return validateAuthHeader(authHeader, credentials, channelProvider, channelId, serviceUrl, new AuthenticationConfiguration()); + public static CompletableFuture validateAuthHeader(String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + String channelId, + String serviceUrl) { + return validateAuthHeader( + authHeader, credentials, channelProvider, channelId, serviceUrl, new AuthenticationConfiguration()); } /** @@ -103,14 +122,20 @@ public static CompletableFuture validateAuthHeader(String authHe * On Join: * @throws AuthenticationException Authentication Error */ - public static CompletableFuture validateAuthHeader(String authHeader, CredentialProvider credentials, ChannelProvider channelProvider, String channelId, String serviceUrl, AuthenticationConfiguration authConfig) { + public static CompletableFuture validateAuthHeader(String authHeader, + CredentialProvider credentials, + ChannelProvider channelProvider, + String channelId, + String serviceUrl, + AuthenticationConfiguration authConfig) { if (StringUtils.isEmpty(authHeader)) { throw new IllegalArgumentException("No authHeader present. Auth is required."); } boolean usingEmulator = EmulatorValidation.isTokenFromEmulator(authHeader); if (usingEmulator) { - return EmulatorValidation.authenticateToken(authHeader, credentials, channelProvider, channelId, authConfig); + return EmulatorValidation.authenticateToken( + authHeader, credentials, channelProvider, channelId, authConfig); } else if (channelProvider == null || channelProvider.isPublicAzure()) { // No empty or null check. Empty can point to issues. Null checks only. if (serviceUrl != null) { @@ -119,9 +144,11 @@ public static CompletableFuture validateAuthHeader(String authHe return ChannelValidation.authenticateToken(authHeader, credentials, channelId, authConfig); } } else if (channelProvider.isGovernment()) { - return GovernmentChannelValidation.authenticateToken(authHeader, credentials, serviceUrl, channelId, authConfig); + return GovernmentChannelValidation.authenticateToken( + authHeader, credentials, serviceUrl, channelId, authConfig); } else { - return EnterpriseChannelValidation.authenticateToken(authHeader, credentials, channelProvider, serviceUrl, channelId, authConfig); + return EnterpriseChannelValidation.authenticateToken( + authHeader, credentials, channelProvider, serviceUrl, channelId, authConfig); } } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index a6d7bad70..f8d69b105 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -47,7 +47,8 @@ public MicrosoftAppCredentials(String appId, String appPassword) { this.appPassword = appPassword; } - public MicrosoftAppCredentials(String appId, String appPassword, String channelAuthTenant) throws MalformedURLException { + public MicrosoftAppCredentials(String appId, String appPassword, String channelAuthTenant) + throws MalformedURLException { this.appId = appId; this.appPassword = appPassword; setChannelAuthTenant(channelAuthTenant); @@ -89,11 +90,13 @@ public static boolean isTrustedServiceUrl(String serviceUrl) { } public static boolean isTrustedServiceUrl(URL url) { - return !trustHostNames.getOrDefault(url.getHost(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); + return !trustHostNames.getOrDefault( + url.getHost(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); } public static boolean isTrustedServiceUrl(HttpUrl url) { - return !trustHostNames.getOrDefault(url.host(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); + return !trustHostNames.getOrDefault( + url.host(), LocalDateTime.MIN).isBefore(LocalDateTime.now().minusMinutes(5)); } public String appId() { diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java index 150bd891f..04a20a343 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/OpenIdMetadata.java @@ -45,7 +45,8 @@ public OpenIdMetadataKey getKey(String keyId) { private String refreshCache() { try { URL openIdUrl = new URL(this.url); - HashMap openIdConf = this.mapper.readValue(openIdUrl, new TypeReference>(){}); + HashMap openIdConf = this.mapper.readValue( + openIdUrl, new TypeReference>(){}); URL keysUrl = new URL(openIdConf.get("jwks_uri")); this.lastUpdated = System.currentTimeMillis(); this.cacheKeys = new UrlJwkProvider(keysUrl); diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java index 98b90ef2f..d704ce6ff 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/TokenValidationParameters.java @@ -18,10 +18,20 @@ public TokenValidationParameters() { } public TokenValidationParameters(TokenValidationParameters other) { - this(other.validateIssuer, other.validIssuers, other.validateAudience, other.validateLifetime, other.clockSkew, other.requireSignedTokens); + this(other.validateIssuer, + other.validIssuers, + other.validateAudience, + other.validateLifetime, + other.clockSkew, + other.requireSignedTokens); } - public TokenValidationParameters(boolean validateIssuer, List validIssuers, boolean validateAudience, boolean validateLifetime, Duration clockSkew, boolean requireSignedTokens) { + public TokenValidationParameters(boolean validateIssuer, + List validIssuers, + boolean validateAudience, + boolean validateLifetime, + Duration clockSkew, + boolean requireSignedTokens) { this.validateIssuer = validateIssuer; this.validIssuers = validIssuers; this.validateAudience = validateAudience; diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java index a29f1f2ae..270031640 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestAttachments.java @@ -53,12 +53,17 @@ public class RestAttachments implements Attachments { interface AttachmentsService { @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Attachments getAttachmentInfo" }) @GET("v3/attachments/{attachmentId}") - Observable> getAttachmentInfo(@Path("attachmentId") String attachmentId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getAttachmentInfo(@Path("attachmentId") String attachmentId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Attachments getAttachment" }) @GET("v3/attachments/{attachmentId}/views/{viewId}") @Streaming - Observable> getAttachment(@Path("attachmentId") String attachmentId, @Path("viewId") String viewId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getAttachment(@Path("attachmentId") String attachmentId, + @Path("viewId") String viewId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); } @@ -85,7 +90,8 @@ public AttachmentInfo getAttachmentInfo(String attachmentId) { * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - public ServiceFuture getAttachmentInfoAsync(String attachmentId, final ServiceCallback serviceCallback) { + public ServiceFuture getAttachmentInfoAsync( + String attachmentId, final ServiceCallback serviceCallback) { return ServiceFuture.fromResponse(getAttachmentInfoWithServiceResponseAsync(attachmentId), serviceCallback); } @@ -98,12 +104,7 @@ public ServiceFuture getAttachmentInfoAsync(String attachmentId, * @return the observable to the AttachmentInfo object */ public Observable getAttachmentInfoAsync(String attachmentId) { - return getAttachmentInfoWithServiceResponseAsync(attachmentId).map(new Func1, AttachmentInfo>() { - @Override - public AttachmentInfo call(ServiceResponse response) { - return response.body(); - } - }); + return getAttachmentInfoWithServiceResponseAsync(attachmentId).map(response -> response.body()); } /** @@ -119,20 +120,19 @@ public Observable> getAttachmentInfoWithServiceR throw new IllegalArgumentException("Parameter attachmentId is required and cannot be null."); } return service.getAttachmentInfo(attachmentId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = getAttachmentInfoDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = getAttachmentInfoDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse getAttachmentInfoDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse getAttachmentInfoDelegate(Response response) + throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .registerError(ErrorResponseException.class) @@ -164,7 +164,9 @@ public InputStream getAttachment(String attachmentId, String viewId) { * @throws IllegalArgumentException thrown if parameters fail the validation * @return the {@link ServiceFuture} object */ - public ServiceFuture getAttachmentAsync(String attachmentId, String viewId, final ServiceCallback serviceCallback) { + public ServiceFuture getAttachmentAsync(String attachmentId, + String viewId, + final ServiceCallback serviceCallback) { return ServiceFuture.fromResponse(getAttachmentWithServiceResponseAsync(attachmentId, viewId), serviceCallback); } @@ -178,12 +180,7 @@ public ServiceFuture getAttachmentAsync(String attachmentId, String * @return the observable to the InputStream object */ public Observable getAttachmentAsync(String attachmentId, String viewId) { - return getAttachmentWithServiceResponseAsync(attachmentId, viewId).map(new Func1, InputStream>() { - @Override - public InputStream call(ServiceResponse response) { - return response.body(); - } - }); + return getAttachmentWithServiceResponseAsync(attachmentId, viewId).map(response -> response.body()); } /** @@ -195,7 +192,8 @@ public InputStream call(ServiceResponse response) { * @throws IllegalArgumentException thrown if parameters fail the validation * @return the observable to the InputStream object */ - public Observable> getAttachmentWithServiceResponseAsync(String attachmentId, String viewId) { + public Observable> getAttachmentWithServiceResponseAsync(String attachmentId, + String viewId) { if (attachmentId == null) { throw new IllegalArgumentException("Parameter attachmentId is required and cannot be null."); } @@ -203,20 +201,19 @@ public Observable> getAttachmentWithServiceResponse throw new IllegalArgumentException("Parameter viewId is required and cannot be null."); } return service.getAttachment(attachmentId, viewId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = getAttachmentDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = getAttachmentDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse getAttachmentDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse getAttachmentDelegate(Response response) + throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(301, new TypeToken() { }.getType()) @@ -224,5 +221,4 @@ private ServiceResponse getAttachmentDelegate(Response> getConversations(@Query("continuationToken") String continuationToken, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getConversations(@Query("continuationToken") String continuationToken, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations createConversation" }) @POST("v3/conversations") - Observable> createConversation(@Body ConversationParameters parameters, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> createConversation(@Body ConversationParameters parameters, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations sendToConversation" }) @POST("v3/conversations/{conversationId}/activities") - Observable> sendToConversation(@Path("conversationId") String conversationId, @Body Activity activity, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> sendToConversation(@Path("conversationId") String conversationId, + @Body Activity activity, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations updateActivity" }) @PUT("v3/conversations/{conversationId}/activities/{activityId}") - Observable> updateActivity(@Path("conversationId") String conversationId, @Path("activityId") String activityId, @Body Activity activity, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> updateActivity(@Path("conversationId") String conversationId, + @Path("activityId") String activityId, + @Body Activity activity, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations replyToActivity" }) @POST("v3/conversations/{conversationId}/activities/{activityId}") - Observable> replyToActivity(@Path("conversationId") String conversationId, @Path("activityId") String activityId, @Body Activity activity, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> replyToActivity(@Path("conversationId") String conversationId, + @Path("activityId") String activityId, + @Body Activity activity, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations deleteActivity" }) @HTTP(path = "v3/conversations/{conversationId}/activities/{activityId}", method = "DELETE", hasBody = true) - Observable> deleteActivity(@Path("conversationId") String conversationId, @Path("activityId") String activityId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> deleteActivity(@Path("conversationId") String conversationId, + @Path("activityId") String activityId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations getConversationMembers" }) @GET("v3/conversations/{conversationId}/members") - Observable> getConversationMembers(@Path("conversationId") String conversationId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getConversationMembers(@Path("conversationId") String conversationId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations deleteConversationMember" }) @HTTP(path = "v3/conversations/{conversationId}/members/{memberId}", method = "DELETE", hasBody = true) - Observable> deleteConversationMember(@Path("conversationId") String conversationId, @Path("memberId") String memberId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> deleteConversationMember(@Path("conversationId") String conversationId, + @Path("memberId") String memberId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations getActivityMembers" }) @GET("v3/conversations/{conversationId}/activities/{activityId}/members") - Observable> getActivityMembers(@Path("conversationId") String conversationId, @Path("activityId") String activityId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getActivityMembers(@Path("conversationId") String conversationId, + @Path("activityId") String activityId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations uploadAttachment" }) @POST("v3/conversations/{conversationId}/attachments") - Observable> uploadAttachment(@Path("conversationId") String conversationId, @Body AttachmentData attachmentUpload, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> uploadAttachment(@Path("conversationId") String conversationId, + @Body AttachmentData attachmentUpload, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations sendConversationHistory" }) @POST("v3/conversations/{conversationId}/activities/history") - Observable> sendConversationHistory(@Path("conversationId") String conversationId, @Body Transcript history, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> sendConversationHistory(@Path("conversationId") String conversationId, + @Body Transcript history, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); @Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.Conversations getConversationPagedMembers" }) @GET("v3/conversations/{conversationId}/pagedmembers") - Observable> getConversationPagedMembers(@Path("conversationId") String conversationId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent); + Observable> getConversationPagedMembers(@Path("conversationId") String conversationId, + @Header("accept-language") String acceptLanguage, + @Header("User-Agent") String userAgent); } /** @@ -122,7 +157,9 @@ public ConversationsResult getConversations() { * @see Conversations#getConversationsAsync */ @Override - public ServiceFuture getConversationsAsync(final ServiceCallback serviceCallback) { + public ServiceFuture getConversationsAsync( + final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(getConversationsWithServiceResponseAsync(), serviceCallback); } @@ -133,12 +170,7 @@ public ServiceFuture getConversationsAsync(final ServiceCal */ @Override public Observable getConversationsAsync() { - return getConversationsWithServiceResponseAsync().map(new Func1, ConversationsResult>() { - @Override - public ConversationsResult call(ServiceResponse response) { - return response.body(); - } - }); + return getConversationsWithServiceResponseAsync().map(response -> response.body()); } /** @@ -150,15 +182,12 @@ public ConversationsResult call(ServiceResponse response) { public Observable> getConversationsWithServiceResponseAsync() { final String continuationToken = null; return service.getConversations(continuationToken, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = getConversationsDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = getConversationsDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } @@ -179,7 +208,9 @@ public ConversationsResult getConversations(String continuationToken) { * @see Conversations#getConversationsAsync */ @Override - public ServiceFuture getConversationsAsync(String continuationToken, final ServiceCallback serviceCallback) { + public ServiceFuture getConversationsAsync( + String continuationToken, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(getConversationsWithServiceResponseAsync(continuationToken), serviceCallback); } @@ -190,12 +221,7 @@ public ServiceFuture getConversationsAsync(String continuat */ @Override public Observable getConversationsAsync(String continuationToken) { - return getConversationsWithServiceResponseAsync(continuationToken).map(new Func1, ConversationsResult>() { - @Override - public ConversationsResult call(ServiceResponse response) { - return response.body(); - } - }); + return getConversationsWithServiceResponseAsync(continuationToken).map(response -> response.body()); } /** @@ -204,7 +230,9 @@ public ConversationsResult call(ServiceResponse response) { * @see Conversations#getConversationsWithServiceResponseAsync */ @Override - public Observable> getConversationsWithServiceResponseAsync(String continuationToken) { + public Observable> getConversationsWithServiceResponseAsync( + String continuationToken) { + return service.getConversations(continuationToken, this.client.getAcceptLanguage(), this.client.getUserAgent()) .flatMap(new Func1, Observable>>() { @Override @@ -219,7 +247,9 @@ public Observable> call(Response getConversationsDelegate(Response response) throws ErrorResponseException, IOException { + private ServiceResponse getConversationsDelegate( + Response response) throws ErrorResponseException, IOException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .registerError(ErrorResponseException.class) @@ -242,7 +272,9 @@ public ConversationResourceResponse createConversation(ConversationParameters pa * @see Conversations#createConversationAsync */ @Override - public ServiceFuture createConversationAsync(ConversationParameters parameters, final ServiceCallback serviceCallback) { + public ServiceFuture createConversationAsync( + ConversationParameters parameters, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(createConversationWithServiceResponseAsync(parameters), serviceCallback); } @@ -253,12 +285,7 @@ public ServiceFuture createConversationAsync(Conve */ @Override public Observable createConversationAsync(ConversationParameters parameters) { - return createConversationWithServiceResponseAsync(parameters).map(new Func1, ConversationResourceResponse>() { - @Override - public ConversationResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + return createConversationWithServiceResponseAsync(parameters).map(response -> response.body()); } /** @@ -267,26 +294,27 @@ public ConversationResourceResponse call(ServiceResponse> createConversationWithServiceResponseAsync(ConversationParameters parameters) { + public Observable> createConversationWithServiceResponseAsync( + ConversationParameters parameters) { + if (parameters == null) { throw new IllegalArgumentException("Parameter parameters is required and cannot be null."); } Validator.validate(parameters); return service.createConversation(parameters, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = createConversationDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = createConversationDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse createConversationDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse createConversationDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -311,7 +339,9 @@ public ResourceResponse sendToConversation(String conversationId, Activity activ * @see Conversations#sendToConversationAsync */ @Override - public ServiceFuture sendToConversationAsync(String conversationId, Activity activity, final ServiceCallback serviceCallback) { + public ServiceFuture sendToConversationAsync( + String conversationId, Activity activity, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(sendToConversationWithServiceResponseAsync(conversationId, activity), serviceCallback); } @@ -322,12 +352,7 @@ public ServiceFuture sendToConversationAsync(String conversati */ @Override public Observable sendToConversationAsync(String conversationId, Activity activity) { - return sendToConversationWithServiceResponseAsync(conversationId, activity).map(new Func1, ResourceResponse>() { - @Override - public ResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + return sendToConversationWithServiceResponseAsync(conversationId, activity).map(response -> response.body()); } /** @@ -336,7 +361,9 @@ public ResourceResponse call(ServiceResponse response) { * @see Conversations#sendToConversationWithServiceResponseAsync */ @Override - public Observable> sendToConversationWithServiceResponseAsync(String conversationId, Activity activity) { + public Observable> sendToConversationWithServiceResponseAsync( + String conversationId, Activity activity) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -345,20 +372,19 @@ public Observable> sendToConversationWithServi } Validator.validate(activity); return service.sendToConversation(conversationId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = sendToConversationDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = sendToConversationDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse sendToConversationDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse sendToConversationDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -383,7 +409,12 @@ public ResourceResponse updateActivity(String conversationId, String activityId, * @see Conversations#updateActivityAsync */ @Override - public ServiceFuture updateActivityAsync(String conversationId, String activityId, Activity activity, final ServiceCallback serviceCallback) { + public ServiceFuture updateActivityAsync( + String conversationId, + String activityId, + Activity activity, + final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(updateActivityWithServiceResponseAsync(conversationId, activityId, activity), serviceCallback); } @@ -394,12 +425,7 @@ public ServiceFuture updateActivityAsync(String conversationId */ @Override public Observable updateActivityAsync(String conversationId, String activityId, Activity activity) { - return updateActivityWithServiceResponseAsync(conversationId, activityId, activity).map(new Func1, ResourceResponse>() { - @Override - public ResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + return updateActivityWithServiceResponseAsync(conversationId, activityId, activity).map(response -> response.body()); } /** @@ -408,7 +434,8 @@ public ResourceResponse call(ServiceResponse response) { * @see Conversations#updateActivityWithServiceResponseAsync */ @Override - public Observable> updateActivityWithServiceResponseAsync(String conversationId, String activityId, Activity activity) { + public Observable> updateActivityWithServiceResponseAsync( + String conversationId, String activityId, Activity activity) { if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -420,20 +447,19 @@ public Observable> updateActivityWithServiceRe } Validator.validate(activity); return service.updateActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = updateActivityDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = updateActivityDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse updateActivityDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse updateActivityDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -449,7 +475,8 @@ private ServiceResponse updateActivityDelegate(Response replyToActivityAsync(String conversationId, String activityId, Activity activity, final ServiceCallback serviceCallback) { - return ServiceFuture.fromResponse(replyToActivityWithServiceResponseAsync(conversationId, activityId, activity), serviceCallback); + public ServiceFuture replyToActivityAsync( + String conversationId, + String activityId, + Activity activity, + final ServiceCallback serviceCallback) { + + return ServiceFuture.fromResponse(replyToActivityWithServiceResponseAsync( + conversationId, activityId, activity), serviceCallback); } /** @@ -468,13 +501,10 @@ public ServiceFuture replyToActivityAsync(String conversationI * @see Conversations#replyToActivityAsync */ @Override - public Observable replyToActivityAsync(String conversationId, String activityId, Activity activity) { - return replyToActivityWithServiceResponseAsync(conversationId, activityId, activity).map(new Func1, ResourceResponse>() { - @Override - public ResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + public Observable replyToActivityAsync(String conversationId, + String activityId, + Activity activity) { + return replyToActivityWithServiceResponseAsync(conversationId, activityId, activity).map(response -> response.body()); } /** @@ -483,7 +513,9 @@ public ResourceResponse call(ServiceResponse response) { * @see Conversations#replyToActivityWithServiceResponseAsync */ @Override - public Observable> replyToActivityWithServiceResponseAsync(String conversationId, String activityId, Activity activity) { + public Observable> replyToActivityWithServiceResponseAsync( + String conversationId, String activityId, Activity activity) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -495,20 +527,19 @@ public Observable> replyToActivityWithServiceR } Validator.validate(activity); return service.replyToActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = replyToActivityDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = replyToActivityDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse replyToActivityDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse replyToActivityDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -533,7 +564,9 @@ public void deleteActivity(String conversationId, String activityId) { * @see Conversations#deleteActivityAsync */ @Override - public ServiceFuture deleteActivityAsync(String conversationId, String activityId, final ServiceCallback serviceCallback) { + public ServiceFuture deleteActivityAsync( + String conversationId, String activityId, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(deleteActivityWithServiceResponseAsync(conversationId, activityId), serviceCallback); } @@ -544,12 +577,7 @@ public ServiceFuture deleteActivityAsync(String conversationId, String act */ @Override public Observable deleteActivityAsync(String conversationId, String activityId) { - return deleteActivityWithServiceResponseAsync(conversationId, activityId).map(new Func1, Void>() { - @Override - public Void call(ServiceResponse response) { - return response.body(); - } - }); + return deleteActivityWithServiceResponseAsync(conversationId, activityId).map(response -> response.body()); } /** @@ -558,7 +586,9 @@ public Void call(ServiceResponse response) { * @see Conversations#deleteActivityWithServiceResponseAsync */ @Override - public Observable> deleteActivityWithServiceResponseAsync(String conversationId, String activityId) { + public Observable> deleteActivityWithServiceResponseAsync( + String conversationId, String activityId) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -566,20 +596,19 @@ public Observable> deleteActivityWithServiceResponseAsync( throw new IllegalArgumentException("Parameter activityId is required and cannot be null."); } return service.deleteActivity(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = deleteActivityDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = deleteActivityDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse deleteActivityDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse deleteActivityDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(202, new TypeToken() { }.getType()) @@ -603,7 +632,9 @@ public List getConversationMembers(String conversationId) { * @see Conversations#getConversationMembersAsync */ @Override - public ServiceFuture> getConversationMembersAsync(String conversationId, final ServiceCallback> serviceCallback) { + public ServiceFuture> getConversationMembersAsync( + String conversationId, final ServiceCallback> serviceCallback) { + return ServiceFuture.fromResponse(getConversationMembersWithServiceResponseAsync(conversationId), serviceCallback); } @@ -614,12 +645,7 @@ public ServiceFuture> getConversationMembersAsync(String co */ @Override public Observable> getConversationMembersAsync(String conversationId) { - return getConversationMembersWithServiceResponseAsync(conversationId).map(new Func1>, List>() { - @Override - public List call(ServiceResponse> response) { - return response.body(); - } - }); + return getConversationMembersWithServiceResponseAsync(conversationId).map(response -> response.body()); } /** @@ -628,25 +654,26 @@ public List call(ServiceResponse> response) * @see Conversations#getConversationMembersWithServiceResponseAsync */ @Override - public Observable>> getConversationMembersWithServiceResponseAsync(String conversationId) { + public Observable>> getConversationMembersWithServiceResponseAsync( + String conversationId) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } return service.getConversationMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>>() { - @Override - public Observable>> call(Response response) { - try { - ServiceResponse> clientResponse = getConversationMembersDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>>) response -> { + try { + ServiceResponse> clientResponse = getConversationMembersDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse> getConversationMembersDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse> getConversationMembersDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory()., ErrorResponseException>newInstance(this.client.serializerAdapter()) .register(200, new TypeToken>() { }.getType()) .registerError(ErrorResponseException.class) @@ -669,8 +696,11 @@ public void deleteConversationMember(String conversationId, String memberId) { * @see Conversations#deleteConversationMemberAsync */ @Override - public ServiceFuture deleteConversationMemberAsync(String conversationId, String memberId, final ServiceCallback serviceCallback) { - return ServiceFuture.fromResponse(deleteConversationMemberWithServiceResponseAsync(conversationId, memberId), serviceCallback); + public ServiceFuture deleteConversationMemberAsync( + String conversationId, String memberId, final ServiceCallback serviceCallback) { + + return ServiceFuture.fromResponse(deleteConversationMemberWithServiceResponseAsync( + conversationId, memberId), serviceCallback); } /** @@ -680,12 +710,8 @@ public ServiceFuture deleteConversationMemberAsync(String conversationId, */ @Override public Observable deleteConversationMemberAsync(String conversationId, String memberId) { - return deleteConversationMemberWithServiceResponseAsync(conversationId, memberId).map(new Func1, Void>() { - @Override - public Void call(ServiceResponse response) { - return response.body(); - } - }); + return deleteConversationMemberWithServiceResponseAsync( + conversationId, memberId).map(response -> response.body()); } /** @@ -694,7 +720,9 @@ public Void call(ServiceResponse response) { * @see Conversations#deleteConversationMemberWithServiceResponseAsync */ @Override - public Observable> deleteConversationMemberWithServiceResponseAsync(String conversationId, String memberId) { + public Observable> deleteConversationMemberWithServiceResponseAsync( + String conversationId, String memberId) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -702,21 +730,20 @@ public Observable> deleteConversationMemberWithServiceResp throw new IllegalArgumentException("Parameter memberId is required and cannot be null."); } return service.deleteConversationMember(conversationId, memberId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = deleteConversationMemberDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = deleteConversationMemberDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse deleteConversationMemberDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse deleteConversationMemberDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(204, new TypeToken() { }.getType()) @@ -740,7 +767,9 @@ public List getActivityMembers(String conversationId, String act * @see Conversations#getActivityMembersAsync */ @Override - public ServiceFuture> getActivityMembersAsync(String conversationId, String activityId, final ServiceCallback> serviceCallback) { + public ServiceFuture> getActivityMembersAsync( + String conversationId, String activityId, final ServiceCallback> serviceCallback) { + return ServiceFuture.fromResponse(getActivityMembersWithServiceResponseAsync(conversationId, activityId), serviceCallback); } @@ -751,12 +780,7 @@ public ServiceFuture> getActivityMembersAsync(String conver */ @Override public Observable> getActivityMembersAsync(String conversationId, String activityId) { - return getActivityMembersWithServiceResponseAsync(conversationId, activityId).map(new Func1>, List>() { - @Override - public List call(ServiceResponse> response) { - return response.body(); - } - }); + return getActivityMembersWithServiceResponseAsync(conversationId, activityId).map(response -> response.body()); } /** @@ -765,7 +789,9 @@ public List call(ServiceResponse> response) * @see Conversations#getActivityMembersWithServiceResponseAsync */ @Override - public Observable>> getActivityMembersWithServiceResponseAsync(String conversationId, String activityId) { + public Observable>> getActivityMembersWithServiceResponseAsync( + String conversationId, String activityId) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -773,20 +799,19 @@ public Observable>> getActivityMembersWithS throw new IllegalArgumentException("Parameter activityId is required and cannot be null."); } return service.getActivityMembers(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>>() { - @Override - public Observable>> call(Response response) { - try { - ServiceResponse> clientResponse = getActivityMembersDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>>) response -> { + try { + ServiceResponse> clientResponse = getActivityMembersDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse> getActivityMembersDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse> getActivityMembersDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory()., ErrorResponseException>newInstance(this.client.serializerAdapter()) .register(200, new TypeToken>() { }.getType()) .registerError(ErrorResponseException.class) @@ -809,7 +834,9 @@ public ResourceResponse uploadAttachment(String conversationId, AttachmentData a * @see Conversations#uploadAttachmentAsync */ @Override - public ServiceFuture uploadAttachmentAsync(String conversationId, AttachmentData attachmentUpload, final ServiceCallback serviceCallback) { + public ServiceFuture uploadAttachmentAsync( + String conversationId, AttachmentData attachmentUpload, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(uploadAttachmentWithServiceResponseAsync(conversationId, attachmentUpload), serviceCallback); } @@ -820,12 +847,8 @@ public ServiceFuture uploadAttachmentAsync(String conversation */ @Override public Observable uploadAttachmentAsync(String conversationId, AttachmentData attachmentUpload) { - return uploadAttachmentWithServiceResponseAsync(conversationId, attachmentUpload).map(new Func1, ResourceResponse>() { - @Override - public ResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + return uploadAttachmentWithServiceResponseAsync( + conversationId, attachmentUpload).map(response -> response.body()); } /** @@ -834,7 +857,9 @@ public ResourceResponse call(ServiceResponse response) { * @see Conversations#uploadAttachmentWithServiceResponseAsync */ @Override - public Observable> uploadAttachmentWithServiceResponseAsync(String conversationId, AttachmentData attachmentUpload) { + public Observable> uploadAttachmentWithServiceResponseAsync( + String conversationId, AttachmentData attachmentUpload) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -843,20 +868,19 @@ public Observable> uploadAttachmentWithService } Validator.validate(attachmentUpload); return service.uploadAttachment(conversationId, attachmentUpload, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = uploadAttachmentDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = uploadAttachmentDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse uploadAttachmentDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse uploadAttachmentDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -882,7 +906,9 @@ public ResourceResponse sendConversationHistory(String conversationId, Transcrip * @see Conversations#sendConversationHistoryAsync */ @Override - public ServiceFuture sendConversationHistoryAsync(String conversationId, Transcript history, final ServiceCallback serviceCallback) { + public ServiceFuture sendConversationHistoryAsync( + String conversationId, Transcript history, final ServiceCallback serviceCallback) { + return ServiceFuture.fromResponse(sendConversationHistoryWithServiceResponseAsync(conversationId, history), serviceCallback); } @@ -893,12 +919,8 @@ public ServiceFuture sendConversationHistoryAsync(String conve */ @Override public Observable sendConversationHistoryAsync(String conversationId, Transcript history) { - return sendConversationHistoryWithServiceResponseAsync(conversationId, history).map(new Func1, ResourceResponse>() { - @Override - public ResourceResponse call(ServiceResponse response) { - return response.body(); - } - }); + return sendConversationHistoryWithServiceResponseAsync( + conversationId, history).map(response -> response.body()); } /** @@ -907,7 +929,9 @@ public ResourceResponse call(ServiceResponse response) { * @see Conversations#sendConversationHistoryWithServiceResponseAsync */ @Override - public Observable> sendConversationHistoryWithServiceResponseAsync(String conversationId, Transcript history) { + public Observable> sendConversationHistoryWithServiceResponseAsync( + String conversationId, Transcript history) { + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } @@ -916,20 +940,19 @@ public Observable> sendConversationHistoryWith } Validator.validate(history); return service.sendConversationHistory(conversationId, history, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = sendConversationHistoryDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = sendConversationHistoryDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse sendConversationHistoryDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse sendConversationHistoryDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .register(201, new TypeToken() { }.getType()) @@ -955,7 +978,9 @@ public PagedMembersResult getConversationPagedMembers(String conversationId){ * @see Conversations#getConversationPagedMembersAsync */ @Override - public ServiceFuture getConversationPagedMembersAsync(String conversationId, final ServiceCallback serviceCallback){ + public ServiceFuture getConversationPagedMembersAsync( + String conversationId, final ServiceCallback serviceCallback){ + return ServiceFuture.fromResponse(getConversationPagedMembersWithServiceResponseAsync(conversationId), serviceCallback); } @@ -966,12 +991,7 @@ public ServiceFuture getConversationPagedMembersAsync(String */ @Override public Observable getConversationPagedMembersAsync(String conversationId){ - return getConversationPagedMembersWithServiceResponseAsync(conversationId).map(new Func1, PagedMembersResult>() { - @Override - public PagedMembersResult call(ServiceResponse response) { - return response.body(); - } - }); + return getConversationPagedMembersWithServiceResponseAsync(conversationId).map(response -> response.body()); } /** @@ -980,29 +1000,29 @@ public PagedMembersResult call(ServiceResponse response) { * @see Conversations#getConversationPagedMembersWithServiceResponseAsync */ @Override - public Observable> getConversationPagedMembersWithServiceResponseAsync(String conversationId){ + public Observable> getConversationPagedMembersWithServiceResponseAsync( + String conversationId){ + if (conversationId == null) { throw new IllegalArgumentException("Parameter conversationId is required and cannot be null."); } return service.getConversationPagedMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent()) - .flatMap(new Func1, Observable>>() { - @Override - public Observable> call(Response response) { - try { - ServiceResponse clientResponse = getConversationPagedMembersDelegate(response); - return Observable.just(clientResponse); - } catch (Throwable t) { - return Observable.error(t); - } + .flatMap((Func1, Observable>>) response -> { + try { + ServiceResponse clientResponse = getConversationPagedMembersDelegate(response); + return Observable.just(clientResponse); + } catch (Throwable t) { + return Observable.error(t); } }); } - private ServiceResponse getConversationPagedMembersDelegate(Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + private ServiceResponse getConversationPagedMembersDelegate( + Response response) throws ErrorResponseException, IOException, IllegalArgumentException { + return this.client.restClient().responseBuilderFactory().newInstance(this.client.serializerAdapter()) .register(200, new TypeToken() { }.getType()) .registerError(ErrorResponseException.class) .build(response); } - } From e5c49e2f25cdac222aa5d356a083de5aaa670d02 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 14:07:18 -0500 Subject: [PATCH 20/26] Corrected all bot-integration-core linter issues. --- .../ClasspathPropertiesConfiguration.java | 19 ++++++++++++++----- .../bot/integration/Configuration.java | 5 +++++ .../ConfigurationChannelProvider.java | 4 ++++ .../ConfigurationCredentialProvider.java | 4 ++++ .../bot/integration/package-info.java | 8 ++++++++ 5 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/package-info.java diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java index f3b3182a1..af8e5f5ec 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ClasspathPropertiesConfiguration.java @@ -1,29 +1,38 @@ package com.microsoft.bot.integration; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.util.Properties; -import org.slf4j.LoggerFactory; /** * Provides access to properties defined in a Properties file located on the classpath. */ public class ClasspathPropertiesConfiguration implements Configuration { + /** + * Holds the properties in application.properties. + */ private Properties properties; /** * Loads properties from the 'application.properties' file. - * @throws IOException */ public ClasspathPropertiesConfiguration() { try { properties = new Properties(); - properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties")); - } - catch (IOException e) { + properties.load(Thread.currentThread().getContextClassLoader() + .getResourceAsStream("application.properties")); + } catch (IOException e) { (LoggerFactory.getLogger(ClasspathPropertiesConfiguration.class)).error("Unable to load properties", e); } } + /** + * Returns a value for the specified property name. + * @param key The property name. + * @return The property value. + */ + @Override public String getProperty(String key) { return properties.getProperty(key); } diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java index 9a98516da..2e4dbab87 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/Configuration.java @@ -7,5 +7,10 @@ * Provides read-only access to configuration properties. */ public interface Configuration { + /** + * Returns a value for the specified property name. + * @param key The property name. + * @return The property value. + */ String getProperty(String key); } diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java index 08054285a..50ca8665d 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationChannelProvider.java @@ -12,6 +12,10 @@ * the key of "ChannelService". */ public class ConfigurationChannelProvider extends SimpleChannelProvider { + /** + * Initializes a new instance using {@link Configuration}. + * @param configuration The configuration to use. + */ public ConfigurationChannelProvider(Configuration configuration) { super(configuration.getProperty("ChannelService")); } diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java index 7750309bf..147f1e520 100644 --- a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/ConfigurationCredentialProvider.java @@ -10,6 +10,10 @@ * Credential provider which uses Configuration to lookup appId and password. */ public class ConfigurationCredentialProvider extends SimpleCredentialProvider { + /** + * Initializes a new instance using a {@link Configuration}. + * @param configuration The Configuration to use. + */ public ConfigurationCredentialProvider(Configuration configuration) { setAppId(configuration.getProperty(MicrosoftAppCredentials.MICROSOFTAPPID)); setPassword(configuration.getProperty(MicrosoftAppCredentials.MICROSOFTAPPPASSWORD)); diff --git a/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/package-info.java b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/package-info.java new file mode 100644 index 000000000..013229b22 --- /dev/null +++ b/libraries/bot-integration-core/src/main/java/com/microsoft/bot/integration/package-info.java @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +/** + * This package contains the classes for bot-integration-core. + */ +package com.microsoft.bot.integration; From e01774729a576979044cc29488da7894ba0b4d56 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 16:10:26 -0500 Subject: [PATCH 21/26] Better comments on Activity.getEntities --- .../com/microsoft/bot/schema/Activity.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java index f173d65d2..42e407e57 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Activity.java @@ -759,6 +759,24 @@ public void setAttachments(List withAttachments) { } /** + * Returns payload version of the Entities in an Activity. + * + * Entities can vary in the number of fields. The {@link Entity} class holds the additional + * fields in {@link Entity#getProperties()}. + * + * To convert to other entity types, use {@link Entity#getAs(Class)}. + * @see Mention + * @see Place + * @see GeoCoordinates + * @see Activity#getMentions() + * + * {@code + * getEntities().stream() + * .filter(entity -> entity.getType().equalsIgnoreCase("mention")) + * .map(entity -> entity.getAs(Mention.class)) + * .collect(Collectors.toCollection(ArrayList::new)); + * } + * * @see #entities */ public List getEntities() { From 8e1146baf9e1af0a9d9270f1bb799e3a3e645478 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Tue, 27 Aug 2019 16:48:31 -0500 Subject: [PATCH 22/26] Changed AdalAuthenticator to return CompletableFuture and use AuthenticationCallback for future retry support if needed. --- .../authentication/AdalAuthenticator.java | 23 ++++++++++++++++--- .../MicrosoftAppCredentials.java | 6 ++--- .../connector/JwtTokenValidationTests.java | 8 +++---- .../MicrosoftAppCredentialsTests.java | 4 ++-- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java index 5ef77adf5..4538e481a 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/AdalAuthenticator.java @@ -4,13 +4,15 @@ package com.microsoft.bot.connector.authentication; +import com.microsoft.aad.adal4j.AuthenticationCallback; import com.microsoft.aad.adal4j.AuthenticationContext; import com.microsoft.aad.adal4j.AuthenticationResult; import com.microsoft.aad.adal4j.ClientCredential; import com.microsoft.bot.connector.ExecutorFactory; +import org.slf4j.LoggerFactory; import java.net.MalformedURLException; -import java.util.concurrent.Future; +import java.util.concurrent.CompletableFuture; public class AdalAuthenticator { private AuthenticationContext context; @@ -25,7 +27,22 @@ public AdalAuthenticator(ClientCredential clientCredential, OAuthConfiguration c ExecutorFactory.getExecutor()); } - public Future acquireToken() { - return context.acquireToken(oAuthConfiguration.scope(), clientCredential, null); + public CompletableFuture acquireToken() { + CompletableFuture tokenFuture = new CompletableFuture<>(); + + context.acquireToken(oAuthConfiguration.scope(), clientCredential, new AuthenticationCallback() { + @Override + public void onSuccess(AuthenticationResult result) { + ExecutorFactory.getExecutor().execute(() -> tokenFuture.complete(result)); + } + + @Override + public void onFailure(Throwable throwable) { + LoggerFactory.getLogger(AdalAuthenticator.class).warn("acquireToken", throwable); + ExecutorFactory.getExecutor().execute(() -> tokenFuture.completeExceptionally(throwable)); + } + }); + + return tokenFuture; } } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java index f8d69b105..e736b033d 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/MicrosoftAppCredentials.java @@ -15,9 +15,9 @@ import java.net.URI; import java.net.URL; import java.time.LocalDateTime; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Future; /** * MicrosoftAppCredentials auth implementation @@ -144,11 +144,11 @@ public String oAuthScope() { return AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE; } - public Future getToken() { + public CompletableFuture getToken() { return getAuthenticator().acquireToken(); } - protected boolean ShouldSetToken(String url) { + protected boolean shouldSetToken(String url) { return isTrustedServiceUrl(url); } diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java index c10ed1c2c..5ab8e498a 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenValidationTests.java @@ -20,12 +20,12 @@ public class JwtTokenValidationTests { private static final String APPID = "2cd87869-38a0-4182-9251-d056e8f0ac24"; private static final String APPPASSWORD = "2.30Vs3VQLKt974F"; - private static String getHeaderToken() throws ExecutionException, InterruptedException { - return String.format("Bearer %s", new MicrosoftAppCredentials(APPID, APPPASSWORD).getToken().get().getAccessToken()); + private static String getHeaderToken() { + return String.format("Bearer %s", new MicrosoftAppCredentials(APPID, APPPASSWORD).getToken().join().getAccessToken()); } - private static String getGovHeaderToken() throws ExecutionException, InterruptedException { - return String.format("Bearer %s", new MicrosoftGovernmentAppCredentials(APPID, APPPASSWORD).getToken().get().getAccessToken()); + private static String getGovHeaderToken() { + return String.format("Bearer %s", new MicrosoftGovernmentAppCredentials(APPID, APPPASSWORD).getToken().join().getAccessToken()); } @Test diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java index 831b964ac..3d79fc555 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/MicrosoftAppCredentialsTests.java @@ -56,9 +56,9 @@ public void ValidateAuthEndpoint() { } @Test - public void GetToken() throws InterruptedException, ExecutionException { + public void GetToken() { MicrosoftAppCredentials credentials = new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F"); - AuthenticationResult token = credentials.getToken().get(); + AuthenticationResult token = credentials.getToken().join(); Assert.assertFalse(StringUtils.isEmpty(token.getAccessToken())); } } From fe48faab0d61348eb9529e09fc06b3e40acf6cc2 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Wed, 28 Aug 2019 11:51:57 -0500 Subject: [PATCH 23/26] Eliminated duplicate user agent generation routines. --- .../bot/connector/ConnectorConfiguration.java | 33 ++++++++++++++++ .../microsoft/bot/connector/UserAgent.java | 39 ++++++++----------- .../connector/rest/RestConnectorClient.java | 24 +----------- 3 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorConfiguration.java diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorConfiguration.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorConfiguration.java new file mode 100644 index 000000000..d125b3847 --- /dev/null +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/ConnectorConfiguration.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.bot.connector; + +import java.io.InputStream; +import java.util.Properties; +import java.util.function.Consumer; + +/** + * Loads configuration properties for bot-connector. + * + * Properties are located in an optional connector.properties file + * in the classpath. + */ +public class ConnectorConfiguration { + public void process(Consumer func) { + final Properties properties = new Properties(); + try { + InputStream propStream = UserAgent.class.getClassLoader() + .getResourceAsStream("connector.properties"); + properties.load(propStream); + func.accept(properties); + } catch (Throwable t) { + Properties p = new Properties(); + p.setProperty("version", "4.0.0"); + func.accept(p); + } + } +} diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java index da084188a..a3763f4db 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/UserAgent.java @@ -1,39 +1,33 @@ -package com.microsoft.bot.connector; +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ -import com.microsoft.bot.connector.rest.RestConnectorClient; +package com.microsoft.bot.connector; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; +import org.slf4j.LoggerFactory; /** - * Retrieve the User Agent string that BotBuilder uses + * Retrieve the User Agent string that Bot SDK uses *

* Conforms to spec: * https://github.com/Microsoft/botbuilder-dotnet/blob/d342cd66d159a023ac435aec0fdf791f93118f5f/doc/UserAgents.md *

*/ public class UserAgent { - - // os/java and botbuilder will never change - static initialize once private static String os_java_botbuilder_cache; static { - String build_version; - final Properties properties = new Properties(); - try { - InputStream propStream = RestConnectorClient.class.getClassLoader() - .getResourceAsStream("project.properties"); - properties.load(propStream); - build_version = properties.getProperty("version"); - } catch (IOException e) { - e.printStackTrace(); - build_version = "4.0.0"; - } - String os_version = System.getProperty("os.name"); - String java_version = System.getProperty("java.version"); - os_java_botbuilder_cache = String.format("BotBuilder/%s (JVM %s; %s)", build_version, java_version, os_version); + new ConnectorConfiguration().process(properties -> { + String build_version = properties.getProperty("version"); + String os_version = System.getProperty("os.name"); + String java_version = System.getProperty("java.version"); + os_java_botbuilder_cache = String.format("BotBuilder/%s (JVM %s; %s)", build_version, java_version, os_version); + + LoggerFactory.getLogger(UserAgent.class).info("UserAgent: {}", os_java_botbuilder_cache); + }); } /** @@ -49,5 +43,4 @@ private UserAgent() { public static String value() { return os_java_botbuilder_cache; } - } diff --git a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java index 127894afd..84be05f83 100644 --- a/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java +++ b/libraries/bot-connector/src/main/java/com/microsoft/bot/connector/rest/RestConnectorClient.java @@ -12,6 +12,7 @@ import com.microsoft.bot.connector.Attachments; import com.microsoft.bot.connector.ConnectorClient; import com.microsoft.bot.connector.Conversations; +import com.microsoft.bot.connector.UserAgent; import com.microsoft.rest.credentials.ServiceClientCredentials; import com.microsoft.rest.RestClient; import com.microsoft.rest.retry.RetryStrategy; @@ -19,10 +20,6 @@ import okhttp3.OkHttpClient; import retrofit2.Retrofit; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - /** * The Bot Connector REST API allows your bot to send and receive messages * to channels configured in the @@ -202,26 +199,9 @@ protected void initialize() { this.attachments = new RestAttachments(restClient().retrofit(), this); this.conversations = new RestConversations(restClient().retrofit(), this); this.azureClient = new AzureClient(this); - - - // Format according to: https://github.com/Microsoft/botbuilder-dotnet/blob/d342cd66d159a023ac435aec0fdf791f93118f5f/doc/UserAgents.md - String build_version; - final Properties properties = new Properties(); - try { - InputStream propStream = RestConnectorClient.class.getClassLoader().getResourceAsStream("project.properties"); - properties.load(propStream); - build_version = properties.getProperty("version"); - } catch (IOException e) { - e.printStackTrace(); - build_version = "4.0.0"; - } - - String os_version = System.getProperty("os.name"); - String java_version = System.getProperty("java.version"); - this.user_agent_string = String.format("BotBuilder/%s (JVM %s; %s)", build_version, java_version, os_version); + this.user_agent_string = UserAgent.value(); } - /** * Gets the User-Agent header for the client. * From da35fcd6eab794393ac17efca68638d786b930f2 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Fri, 30 Aug 2019 08:45:50 -0500 Subject: [PATCH 24/26] Setup skeleton module for all packages that mirror the dotnet project. --- libraries/bot-ai-luis-v3/pom.xml | 201 +++++++++++ libraries/bot-ai-qna/pom.xml | 197 +++++++++++ libraries/bot-applicationinsights/pom.xml | 193 ++++++++++ libraries/bot-azure/pom.xml | 197 +++++++++++ libraries/bot-builder/pom.xml | 4 +- .../src/main/resources/log4j2.json | 25 -- libraries/bot-configuration/pom.xml | 188 ++++++++++ libraries/bot-connector/pom.xml | 1 - libraries/bot-dialogs/pom.xml | 192 ++++++++++ .../com/microsoft/bot}/dialogs/Dialog.java | 222 ++++++------ .../bot}/dialogs/DialogCompletion.java | 108 +++--- .../bot}/dialogs/DialogContainer.java | 100 +++--- .../microsoft/bot}/dialogs/DialogContext.java | 334 +++++++++--------- .../com/microsoft/bot}/dialogs/IDialog.java | 38 +- .../bot}/dialogs/IDialogContinue.java | 42 +-- .../bot}/dialogs/MessageOptions.java | 2 +- .../bot/dialogs}/prompts/Choice.java | 2 +- libraries/bot-integration-core/pom.xml | 6 - pom.xml | 45 ++- 19 files changed, 1637 insertions(+), 460 deletions(-) create mode 100644 libraries/bot-ai-luis-v3/pom.xml create mode 100644 libraries/bot-ai-qna/pom.xml create mode 100644 libraries/bot-applicationinsights/pom.xml create mode 100644 libraries/bot-azure/pom.xml delete mode 100644 libraries/bot-builder/src/main/resources/log4j2.json create mode 100644 libraries/bot-configuration/pom.xml create mode 100644 libraries/bot-dialogs/pom.xml rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/Dialog.java (92%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/DialogCompletion.java (92%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/DialogContainer.java (96%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/DialogContext.java (96%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/IDialog.java (83%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/IDialogContinue.java (85%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot}/dialogs/MessageOptions.java (97%) rename libraries/{bot-builder/src/main/java/com/microsoft/bot/builder => bot-dialogs/src/main/java/com/microsoft/bot/dialogs}/prompts/Choice.java (95%) diff --git a/libraries/bot-ai-luis-v3/pom.xml b/libraries/bot-ai-luis-v3/pom.xml new file mode 100644 index 000000000..a66c04a51 --- /dev/null +++ b/libraries/bot-ai-luis-v3/pom.xml @@ -0,0 +1,201 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-ai-luis-v3 + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Dialogs + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + + org.slf4j + slf4j-api + + + + com.microsoft.bot + bot-builder + + + com.microsoft.bot + bot-configuration + + + com.microsoft.bot + bot-applicationinsights + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + **/** + + + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-ai-luis-v3 + xml + 256m + + true + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-ai-qna/pom.xml b/libraries/bot-ai-qna/pom.xml new file mode 100644 index 000000000..2846e281e --- /dev/null +++ b/libraries/bot-ai-qna/pom.xml @@ -0,0 +1,197 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-ai-qna + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Dialogs + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + + org.slf4j + slf4j-api + + + + com.microsoft.bot + bot-builder + + + com.microsoft.bot + bot-configuration + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + **/** + + + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-ai-qna + xml + 256m + + true + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-applicationinsights/pom.xml b/libraries/bot-applicationinsights/pom.xml new file mode 100644 index 000000000..75e27215b --- /dev/null +++ b/libraries/bot-applicationinsights/pom.xml @@ -0,0 +1,193 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-applicationinsights + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Dialogs + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + + org.slf4j + slf4j-api + + + + com.microsoft.bot + bot-builder + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + **/** + + + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-applicationinsights + xml + 256m + + true + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-azure/pom.xml b/libraries/bot-azure/pom.xml new file mode 100644 index 000000000..d71aa6ec8 --- /dev/null +++ b/libraries/bot-azure/pom.xml @@ -0,0 +1,197 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-azure + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Integration Core + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + org.slf4j + slf4j-api + + + com.microsoft.bot + bot-builder + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-azure + xml + 256m + + true + + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-builder/pom.xml b/libraries/bot-builder/pom.xml index 4d0696e65..404ce93b1 100644 --- a/libraries/bot-builder/pom.xml +++ b/libraries/bot-builder/pom.xml @@ -12,7 +12,7 @@ bot-builder jar - 4.0-SNAPSHOT + 4.0.0-SNAPSHOT ${project.groupId}:${project.artifactId} Bot Framework Connector @@ -92,12 +92,10 @@ com.microsoft.bot bot-schema - 4.0.0-SNAPSHOT com.microsoft.bot bot-connector - 4.0.0-SNAPSHOT diff --git a/libraries/bot-builder/src/main/resources/log4j2.json b/libraries/bot-builder/src/main/resources/log4j2.json deleted file mode 100644 index b183e4d9c..000000000 --- a/libraries/bot-builder/src/main/resources/log4j2.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "configuration": { - "name": "Default", - "appenders": { - "Console": { - "name": "Console-Appender", - "target": "SYSTEM_OUT", - "PatternLayout": {"pattern": "[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"} - } - }, - "loggers": { - "logger": [ - { - "name": "com.microsoft.bot.builder", - "level": "debug", - "appender-ref": [{"ref": "Console-Appender", "level": "debug"}] - } - ], - "root": { - "level": "warn", - "appender-ref": {"ref": "Console-Appender","level": "warn"} - } - } - } -} diff --git a/libraries/bot-configuration/pom.xml b/libraries/bot-configuration/pom.xml new file mode 100644 index 000000000..833984abe --- /dev/null +++ b/libraries/bot-configuration/pom.xml @@ -0,0 +1,188 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-configuration + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Dialogs + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + + org.slf4j + slf4j-api + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + **/** + + + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-configuration + xml + 256m + + true + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-connector/pom.xml b/libraries/bot-connector/pom.xml index b88c170e0..61697460c 100644 --- a/libraries/bot-connector/pom.xml +++ b/libraries/bot-connector/pom.xml @@ -94,7 +94,6 @@ com.microsoft.bot bot-schema - 4.0.0-SNAPSHOT diff --git a/libraries/bot-dialogs/pom.xml b/libraries/bot-dialogs/pom.xml new file mode 100644 index 000000000..6ab351abb --- /dev/null +++ b/libraries/bot-dialogs/pom.xml @@ -0,0 +1,192 @@ + + + 4.0.0 + + + com.microsoft.bot + bot-java + 4.0.0 + ../../pom.xml + + + bot-dialogs + jar + 4.0.0-SNAPSHOT + + ${project.groupId}:${project.artifactId} + Bot Framework Dialogs + https://dev.botframework.com/ + + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + Bot Framework Development + + Microsoft + https://dev.botframework.com/ + + + + + scm:git:https://github.com/Microsoft/botbuilder-java + scm:git:https://github.com/Microsoft/botbuilder-java + https://github.com/Microsoft/botbuilder-java + + + + UTF-8 + false + + + + + junit + junit + + + org.slf4j + slf4j-api + + + + com.microsoft.bot + bot-builder + + + + + + MyGet + ${repo.url} + + + + + + MyGet + ${repo.url} + + + + + + build + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + true + + **/** + + + + + + org.eluder.coveralls + coveralls-maven-plugin + + yourcoverallsprojectrepositorytoken + + + + org.codehaus.mojo + cobertura-maven-plugin + + ../../cobertura-report/bot-dialogs + xml + 256m + + true + + + + + + + + publish + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + + + diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/Dialog.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Dialog.java similarity index 92% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/Dialog.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Dialog.java index 729367b74..23bb2718f 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/Dialog.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Dialog.java @@ -1,111 +1,111 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -package com.microsoft.bot.builder.dialogs; - - -import com.microsoft.bot.builder.BotAssert; -import com.microsoft.bot.builder.TurnContext; - -import java.util.HashMap; -import java.util.concurrent.CompletableFuture; - -/** - * Base class for controls - */ -public abstract class Dialog -{ - /** - * Starts the dialog. Depending on the dialog, its possible for the dialog to finish - * immediately so it's advised to check the completion Object returned by `begin()` and ensure - * that the dialog is still active before continuing. - * @param context Context for the current turn of the conversation with the user. - * @param state A state Object that the dialog will use to persist its current state. This should be an empty Object which the dialog will populate. The bot should persist this with its other conversation state for as long as the dialog is still active. - * @param options (Optional) additional options supported by the dialog. - * @return DialogCompletion result - */ - public CompletableFuture Begin(TurnContext context, HashMap state) - { - return Begin(context, state, null); - } - public CompletableFuture Begin(TurnContext context, HashMap state, HashMap options) - { - BotAssert.ContextNotNull(context); - if (state == null) - throw new NullPointerException("HashMap state"); - - // Create empty dialog set and ourselves to it - // TODO: Complete - //DialogSet dialogs = new DialogSet(); - //dialogs.Add("dialog", (IDialog)this); - - // Start the control - //HashMap result = null; - - /* - // TODO Complete - - await dc.Begin("dialog", options); - */ - CompletableFuture result = null; - /* - if (dc.ActiveDialog != null) { - result = new DialogCompletion(); - result.setIsActive(true); - result.setIsCompleted(false); - } - else{ - result = new DialogCompletion(); - result.setIsActive(false); - result.setIsCompleted(true); - result.setResult(result); - } - */ - return result; - } - - /** - * Passes a users reply to the dialog for further processing.The bot should keep calling - * 'continue()' for future turns until the dialog returns a completion Object with - * 'isCompleted == true'. To cancel or interrupt the prompt simply delete the `state` Object - * being persisted. - * @param context Context for the current turn of the conversation with the user. - * @param state A state Object that was previously initialized by a call to [begin()](#begin). - * @return DialogCompletion result - */ - public CompletableFuture Continue(TurnContext context, HashMap state) - { - BotAssert.ContextNotNull(context); - if (state == null) - throw new NullPointerException("HashMap"); - - // Create empty dialog set and ourselves to it - // TODO: daveta - //DialogSet dialogs = new DialogSet(); - //dialogs.Add("dialog", (IDialog)this); - - // Continue the dialog - //HashMap result = null; - CompletableFuture result = null; - /* - TODO: daveta - var dc = new DialogContext(dialogs, context, state, (r) => { result = r; }); - if (dc.ActiveDialog != null) - { - await dc.Continue(); - return dc.ActiveDialog != null - ? - new DialogCompletion { IsActive = true, IsCompleted = false } - : - new DialogCompletion { IsActive = false, IsCompleted = true, Result = result }; - } - else - { - return new DialogCompletion { IsActive = false, IsCompleted = false }; - } - */ - - return result; - - } -} - +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.bot.dialogs; + + +import com.microsoft.bot.builder.BotAssert; +import com.microsoft.bot.builder.TurnContext; + +import java.util.HashMap; +import java.util.concurrent.CompletableFuture; + +/** + * Base class for controls + */ +public abstract class Dialog +{ + /** + * Starts the dialog. Depending on the dialog, its possible for the dialog to finish + * immediately so it's advised to check the completion Object returned by `begin()` and ensure + * that the dialog is still active before continuing. + * @param context Context for the current turn of the conversation with the user. + * @param state A state Object that the dialog will use to persist its current state. This should be an empty Object which the dialog will populate. The bot should persist this with its other conversation state for as long as the dialog is still active. + * @param options (Optional) additional options supported by the dialog. + * @return DialogCompletion result + */ + public CompletableFuture Begin(TurnContext context, HashMap state) + { + return Begin(context, state, null); + } + public CompletableFuture Begin(TurnContext context, HashMap state, HashMap options) + { + BotAssert.ContextNotNull(context); + if (state == null) + throw new NullPointerException("HashMap state"); + + // Create empty dialog set and ourselves to it + // TODO: Complete + //DialogSet dialogs = new DialogSet(); + //dialogs.Add("dialog", (IDialog)this); + + // Start the control + //HashMap result = null; + + /* + // TODO Complete + + await dc.Begin("dialog", options); + */ + CompletableFuture result = null; + /* + if (dc.ActiveDialog != null) { + result = new DialogCompletion(); + result.setIsActive(true); + result.setIsCompleted(false); + } + else{ + result = new DialogCompletion(); + result.setIsActive(false); + result.setIsCompleted(true); + result.setResult(result); + } + */ + return result; + } + + /** + * Passes a users reply to the dialog for further processing.The bot should keep calling + * 'continue()' for future turns until the dialog returns a completion Object with + * 'isCompleted == true'. To cancel or interrupt the prompt simply delete the `state` Object + * being persisted. + * @param context Context for the current turn of the conversation with the user. + * @param state A state Object that was previously initialized by a call to [begin()](#begin). + * @return DialogCompletion result + */ + public CompletableFuture Continue(TurnContext context, HashMap state) + { + BotAssert.ContextNotNull(context); + if (state == null) + throw new NullPointerException("HashMap"); + + // Create empty dialog set and ourselves to it + // TODO: daveta + //DialogSet dialogs = new DialogSet(); + //dialogs.Add("dialog", (IDialog)this); + + // Continue the dialog + //HashMap result = null; + CompletableFuture result = null; + /* + TODO: daveta + var dc = new DialogContext(dialogs, context, state, (r) => { result = r; }); + if (dc.ActiveDialog != null) + { + await dc.Continue(); + return dc.ActiveDialog != null + ? + new DialogCompletion { IsActive = true, IsCompleted = false } + : + new DialogCompletion { IsActive = false, IsCompleted = true, Result = result }; + } + else + { + return new DialogCompletion { IsActive = false, IsCompleted = false }; + } + */ + + return result; + + } +} + diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogCompletion.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogCompletion.java similarity index 92% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogCompletion.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogCompletion.java index a978effcc..826064ed2 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogCompletion.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogCompletion.java @@ -1,54 +1,54 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.bot.builder.dialogs; - -import java.util.HashMap; - -/** - * Result returned to the caller of one of the various stack manipulation methods and used to - * return the result from a final call to `DialogContext.end()` to the bots logic. - */ -public class DialogCompletion -{ - - - /** - * If 'true' the dialog is still active. - */ - boolean _isActive; - public void setIsActive(boolean isActive) { - this._isActive = isActive; - } - public boolean getIsActive() { - return this._isActive; - } - - /** - * If 'true' the dialog just completed and the final [result](#result) can be retrieved. - */ - boolean _isCompleted; - public void setIsCompleted(boolean isCompleted) - { - this._isCompleted = isCompleted; - } - public boolean getIsCompleted() - { - return this._isCompleted; - } - - /** - * Result returned by a dialog that was just ended.This will only be populated in certain - * cases: - * - The bot calls `dc.begin()` to start a new dialog and the dialog ends immediately. - * - The bot calls `dc.continue()` and a dialog that was active ends. - * In all cases where it's populated, [active](#active) will be `false`. - */ - HashMap _result; - public HashMap getResult() { - return _result; - } - public void setResult(HashMap result) { - this._result = result; - } -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.dialogs; + +import java.util.HashMap; + +/** + * Result returned to the caller of one of the various stack manipulation methods and used to + * return the result from a final call to `DialogContext.end()` to the bots logic. + */ +public class DialogCompletion +{ + + + /** + * If 'true' the dialog is still active. + */ + boolean _isActive; + public void setIsActive(boolean isActive) { + this._isActive = isActive; + } + public boolean getIsActive() { + return this._isActive; + } + + /** + * If 'true' the dialog just completed and the final [result](#result) can be retrieved. + */ + boolean _isCompleted; + public void setIsCompleted(boolean isCompleted) + { + this._isCompleted = isCompleted; + } + public boolean getIsCompleted() + { + return this._isCompleted; + } + + /** + * Result returned by a dialog that was just ended.This will only be populated in certain + * cases: + * - The bot calls `dc.begin()` to start a new dialog and the dialog ends immediately. + * - The bot calls `dc.continue()` and a dialog that was active ends. + * In all cases where it's populated, [active](#active) will be `false`. + */ + HashMap _result; + public HashMap getResult() { + return _result; + } + public void setResult(HashMap result) { + this._result = result; + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContainer.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContainer.java similarity index 96% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContainer.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContainer.java index 51d0f50d8..c76181297 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContainer.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContainer.java @@ -1,50 +1,50 @@ -/* -public class DialogContainer implements IDialogContinue - - -{ - protected DialogSet Dialogs { get; set; } - protected string DialogId { get; set; } - - public DialogContainer(string dialogId, DialogSet dialogs = null) - { - if (string.IsNullOrEmpty(dialogId)) - throw new ArgumentNullException(nameof(dialogId)); - - Dialogs dialogs = (dialogs != null) ? dialogs : new DialogSet(); - DialogId = dialogId; - } - - public async Task DialogBegin(DialogContext dc, IDictionary dialogArgs = null) - { - if (dc == null) - throw new ArgumentNullException(nameof(dc)); - - // Start the controls entry point dialog. - IDictionary result = null; - var cdc = new DialogContext(this.Dialogs, dc.Context, dc.ActiveDialog.State, (r) => { result = r; }); - await cdc.Begin(DialogId, dialogArgs); - // End if the controls dialog ends. - if (cdc.ActiveDialog == null) - { - await dc.End(result); - } - } - - public async Task DialogContinue(DialogContext dc) - { - if (dc == null) - throw new ArgumentNullException(nameof(dc)); - - // Continue controls dialog stack. - IDictionary result = null; - var cdc = new DialogContext(this.Dialogs, dc.Context, dc.ActiveDialog.State, (r) => { result = r; }); - await cdc.Continue(); - // End if the controls dialog ends. - if (cdc.ActiveDialog == null) - { - await dc.End(result); - } - } -} -*/ +/* +public class DialogContainer implements IDialogContinue + + +{ + protected DialogSet Dialogs { get; set; } + protected string DialogId { get; set; } + + public DialogContainer(string dialogId, DialogSet dialogs = null) + { + if (string.IsNullOrEmpty(dialogId)) + throw new ArgumentNullException(nameof(dialogId)); + + Dialogs dialogs = (dialogs != null) ? dialogs : new DialogSet(); + DialogId = dialogId; + } + + public async Task DialogBegin(DialogContext dc, IDictionary dialogArgs = null) + { + if (dc == null) + throw new ArgumentNullException(nameof(dc)); + + // Start the controls entry point dialog. + IDictionary result = null; + var cdc = new DialogContext(this.Dialogs, dc.Context, dc.ActiveDialog.State, (r) => { result = r; }); + await cdc.Begin(DialogId, dialogArgs); + // End if the controls dialog ends. + if (cdc.ActiveDialog == null) + { + await dc.End(result); + } + } + + public async Task DialogContinue(DialogContext dc) + { + if (dc == null) + throw new ArgumentNullException(nameof(dc)); + + // Continue controls dialog stack. + IDictionary result = null; + var cdc = new DialogContext(this.Dialogs, dc.Context, dc.ActiveDialog.State, (r) => { result = r; }); + await cdc.Continue(); + // End if the controls dialog ends. + if (cdc.ActiveDialog == null) + { + await dc.End(result); + } + } +} +*/ diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContext.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContext.java similarity index 96% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContext.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContext.java index 53531a32c..2a733f8ac 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/DialogContext.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContext.java @@ -1,167 +1,167 @@ -package com.microsoft.bot.builder.dialogs; - -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. -// -// Microsoft Bot Framework: http://botframework.com -// -// Bot Builder SDK GitHub: -// https://github.com/Microsoft/BotBuilder -// -// Copyright (c) Microsoft Corporation -// All rights reserved. -// -// MIT License: -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -/** - * Encapsulates a method that represents the code to execute after a result is available. - * - * The result is often a message from the user. - * - * @param T The type of the result. - * @param context The dialog context. - * @param result The result. - * @return A task that represents the code that will resume after the result is available. - */ - -/* -public interface ResumeAfter -{ - CompletableFuture invoke(DialogContext contenxt, Available) -} - -public delegate Task ResumeAfter(IDialogContext context, IAwaitable result); -*/ - -/** - * Encapsulate a method that represents the code to start a dialog. - * @param context The dialog context. - * @return A task that represents the start code for a dialog. - */ -//public delegate Task StartAsync(IDialogContext context); - - - -/** - * The context for the execution of a dialog's conversational process. - */ -// DAVETA: TODO -// public interface DialogContext extends -public interface DialogContext { - } - - -/** - * Helper methods. - */ -/* -public static partial class Extensions -{*/ - /** - * Post a message to be sent to the user, using previous messages to establish a conversation context. - * - * If the locale parameter is not set, locale of the incoming message will be used for reply. - * - * @param botToUser Communication channel to use. - * @param text The message text. - * @param locale The locale of the text. - * @return A task that represents the post operation. - */ -/* - public static async Task PostAsync(this BotToUser botToUser, string text, string locale = null) - { - var message = botToUser.MakeMessage(); - message.Text = text; - - if (!string.IsNullOrEmpty(locale)) - { - message.Locale = locale; - } - - await botToUser.PostAsync(message); - } -*/ - - - /** - * Post a message and optional SSML to be sent to the user, using previous messages to establish a conversation context. - * - * If the locale parameter is not set, locale of the incoming message will be used for reply. - * - * @param botToUser Communication channel to use. - * @param text The message text. - * @param speak The SSML markup for text to speech. - * @param options The options for the message. - * @param locale The locale of the text. - * @return A task that represents the post operation. - */ - /* public static async Task SayAsync(this BotToUser botToUser, string text, string speak = null, MessageOptions options = null, string locale = null) - { - var message = botToUser.MakeMessage(); - - message.Text = text; - message.Speak = speak; - - if (!string.IsNullOrEmpty(locale)) - { - message.Locale = locale; - } - - if (options != null) - { - message.InputHint = options.InputHint; - message.TextFormat = options.TextFormat; - message.AttachmentLayout = options.AttachmentLayout; - message.Attachments = options.Attachments; - message.Entities = options.Entities; - } - - await botToUser.PostAsync(message); - }*/ - - /** - * Suspend the current dialog until the user has sent a message to the bot. - * @param stack The dialog stack. - * @param resume The method to resume when the message has been received. - */ -/* - public static void Wait(this IDialogStack stack, ResumeAfter resume) - { - stack.Wait(resume); - } -*/ - - /** - * Call a child dialog, add it to the top of the stack and post the message to the child dialog. - * @param R The type of result expected from the child dialog. - * @param stack The dialog stack. - * @param child The child dialog. - * @param resume The method to resume when the child dialog has completed. - * @param message The message that will be posted to child dialog. - * @return A task representing the Forward operation. - */ -/* public static async Task Forward(this IDialogStack stack, IDialog child, ResumeAfter resume, MessageActivity message) - { - await stack.Forward(child, resume, message, token); - } -}*/ +package com.microsoft.bot.dialogs; + +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// +// Microsoft Bot Framework: http://botframework.com +// +// Bot Builder SDK GitHub: +// https://github.com/Microsoft/BotBuilder +// +// Copyright (c) Microsoft Corporation +// All rights reserved. +// +// MIT License: +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +/** + * Encapsulates a method that represents the code to execute after a result is available. + * + * The result is often a message from the user. + * + * @param T The type of the result. + * @param context The dialog context. + * @param result The result. + * @return A task that represents the code that will resume after the result is available. + */ + +/* +public interface ResumeAfter +{ + CompletableFuture invoke(DialogContext contenxt, Available) +} + +public delegate Task ResumeAfter(IDialogContext context, IAwaitable result); +*/ + +/** + * Encapsulate a method that represents the code to start a dialog. + * @param context The dialog context. + * @return A task that represents the start code for a dialog. + */ +//public delegate Task StartAsync(IDialogContext context); + + + +/** + * The context for the execution of a dialog's conversational process. + */ +// DAVETA: TODO +// public interface DialogContext extends +public interface DialogContext { + } + + +/** + * Helper methods. + */ +/* +public static partial class Extensions +{*/ + /** + * Post a message to be sent to the user, using previous messages to establish a conversation context. + * + * If the locale parameter is not set, locale of the incoming message will be used for reply. + * + * @param botToUser Communication channel to use. + * @param text The message text. + * @param locale The locale of the text. + * @return A task that represents the post operation. + */ +/* + public static async Task PostAsync(this BotToUser botToUser, string text, string locale = null) + { + var message = botToUser.MakeMessage(); + message.Text = text; + + if (!string.IsNullOrEmpty(locale)) + { + message.Locale = locale; + } + + await botToUser.PostAsync(message); + } +*/ + + + /** + * Post a message and optional SSML to be sent to the user, using previous messages to establish a conversation context. + * + * If the locale parameter is not set, locale of the incoming message will be used for reply. + * + * @param botToUser Communication channel to use. + * @param text The message text. + * @param speak The SSML markup for text to speech. + * @param options The options for the message. + * @param locale The locale of the text. + * @return A task that represents the post operation. + */ + /* public static async Task SayAsync(this BotToUser botToUser, string text, string speak = null, MessageOptions options = null, string locale = null) + { + var message = botToUser.MakeMessage(); + + message.Text = text; + message.Speak = speak; + + if (!string.IsNullOrEmpty(locale)) + { + message.Locale = locale; + } + + if (options != null) + { + message.InputHint = options.InputHint; + message.TextFormat = options.TextFormat; + message.AttachmentLayout = options.AttachmentLayout; + message.Attachments = options.Attachments; + message.Entities = options.Entities; + } + + await botToUser.PostAsync(message); + }*/ + + /** + * Suspend the current dialog until the user has sent a message to the bot. + * @param stack The dialog stack. + * @param resume The method to resume when the message has been received. + */ +/* + public static void Wait(this IDialogStack stack, ResumeAfter resume) + { + stack.Wait(resume); + } +*/ + + /** + * Call a child dialog, add it to the top of the stack and post the message to the child dialog. + * @param R The type of result expected from the child dialog. + * @param stack The dialog stack. + * @param child The child dialog. + * @param resume The method to resume when the child dialog has completed. + * @param message The message that will be posted to child dialog. + * @return A task representing the Forward operation. + */ +/* public static async Task Forward(this IDialogStack stack, IDialog child, ResumeAfter resume, MessageActivity message) + { + await stack.Forward(child, resume, message, token); + } +}*/ diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialog.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialog.java similarity index 83% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialog.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialog.java index 8cb58b529..366a69d0c 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialog.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialog.java @@ -1,19 +1,19 @@ -package com.microsoft.bot.builder.dialogs; - -// TODO: daveta remove this - not sure where this came from -/** - * Interface for all Dialog objects that can be added to a `DialogSet`. The dialog should generally - * be a singleton and added to a dialog set using `DialogSet.add()` at which point it will be - * assigned a unique ID. - */ -public interface IDialog -{ - /** - * Method called when a new dialog has been pushed onto the stack and is being activated. - * @param dc The dialog context for the current turn of conversation. - * @param dialogArgs (Optional) arguments that were passed to the dialog during `begin()` call that started the instance. - */ - //CompleteableFuture DialogBegin(DialogContext dc, IDictionary dialogArgs = null); - //CompleteableFuture DialogBegin(DialogContext dc, HashMap dialogArgs); - //CompleteableFuture DialogBegin(DialogContext dc); -} +package com.microsoft.bot.dialogs; + +// TODO: daveta remove this - not sure where this came from +/** + * Interface for all Dialog objects that can be added to a `DialogSet`. The dialog should generally + * be a singleton and added to a dialog set using `DialogSet.add()` at which point it will be + * assigned a unique ID. + */ +public interface IDialog +{ + /** + * Method called when a new dialog has been pushed onto the stack and is being activated. + * @param dc The dialog context for the current turn of conversation. + * @param dialogArgs (Optional) arguments that were passed to the dialog during `begin()` call that started the instance. + */ + //CompleteableFuture DialogBegin(DialogContext dc, IDictionary dialogArgs = null); + //CompleteableFuture DialogBegin(DialogContext dc, HashMap dialogArgs); + //CompleteableFuture DialogBegin(DialogContext dc); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialogContinue.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialogContinue.java similarity index 85% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialogContinue.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialogContinue.java index 0abb6879e..bf6c30de2 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/IDialogContinue.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/IDialogContinue.java @@ -1,21 +1,21 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -package com.microsoft.bot.builder.dialogs; - - -import java.util.concurrent.CompletableFuture; - -/** - * Interface Dialog objects that can be continued. - */ -public interface IDialogContinue extends IDialog -{ - /** - * Method called when an instance of the dialog is the "current" dialog and the - * user replies with a new activity. The dialog will generally continue to receive the users - * replies until it calls either `DialogSet.end()` or `DialogSet.begin()`. - * If this method is NOT implemented then the dialog will automatically be ended when the user replies. - * @param dc The dialog context for the current turn of conversation. - */ - CompletableFuture DialogContinue(DialogContext dc); -} +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.microsoft.bot.dialogs; + + +import java.util.concurrent.CompletableFuture; + +/** + * Interface Dialog objects that can be continued. + */ +public interface IDialogContinue extends IDialog +{ + /** + * Method called when an instance of the dialog is the "current" dialog and the + * user replies with a new activity. The dialog will generally continue to receive the users + * replies until it calls either `DialogSet.end()` or `DialogSet.begin()`. + * If this method is NOT implemented then the dialog will automatically be ended when the user replies. + * @param dc The dialog context for the current turn of conversation. + */ + CompletableFuture DialogContinue(DialogContext dc); +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/MessageOptions.java similarity index 97% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/MessageOptions.java index d64b69152..ff765b72b 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/dialogs/MessageOptions.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/MessageOptions.java @@ -1,4 +1,4 @@ -package com.microsoft.bot.builder.dialogs; +package com.microsoft.bot.dialogs; import com.microsoft.bot.schema.AttachmentLayoutTypes; import com.microsoft.bot.schema.TextFormatTypes; diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/prompts/Choice.java similarity index 95% rename from libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java rename to libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/prompts/Choice.java index ba6f9cfd2..53b32c613 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/prompts/Choice.java +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/prompts/Choice.java @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.microsoft.bot.builder.prompts; +package com.microsoft.bot.dialogs.prompts; import com.microsoft.bot.schema.CardAction; diff --git a/libraries/bot-integration-core/pom.xml b/libraries/bot-integration-core/pom.xml index 64233d8a4..88a960d5f 100644 --- a/libraries/bot-integration-core/pom.xml +++ b/libraries/bot-integration-core/pom.xml @@ -57,16 +57,10 @@ com.microsoft.bot bot-schema - 4.0.0-SNAPSHOT com.microsoft.bot bot-connector - 4.0.0-SNAPSHOT - - - org.slf4j - slf4j-api diff --git a/pom.xml b/pom.xml index b838a9558..b5c0771e4 100644 --- a/pom.xml +++ b/pom.xml @@ -128,14 +128,57 @@ test + + com.microsoft.bot + bot-schema + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-connector + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-builder + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-dialogs + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-configuration + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-ai-luis-v3 + 4.0.0-SNAPSHOT + + + com.microsoft.bot + bot-applicationinsights + 4.0.0-SNAPSHOT + + libraries/bot-schema - libraries/bot-builder libraries/bot-connector + libraries/bot-builder libraries/bot-integration-core + libraries/bot-dialogs + libraries/bot-configuration + libraries/bot-ai-luis-v3 + libraries/bot-ai-qna + libraries/bot-applicationinsights + libraries/bot-azure + samples/bot-connector-sample samples/servlet-echo samples/spring-echo From 33e47995f2989e72f8e4061b436c70ab7ce21da6 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Fri, 30 Aug 2019 12:45:56 -0500 Subject: [PATCH 25/26] Added external module dependencies. --- libraries/bot-ai-luis-v3/pom.xml | 7 ++++++- libraries/bot-applicationinsights/pom.xml | 7 ++++++- libraries/bot-dialogs/pom.xml | 11 +++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libraries/bot-ai-luis-v3/pom.xml b/libraries/bot-ai-luis-v3/pom.xml index a66c04a51..31dcbd210 100644 --- a/libraries/bot-ai-luis-v3/pom.xml +++ b/libraries/bot-ai-luis-v3/pom.xml @@ -50,12 +50,17 @@ junit junit - org.slf4j slf4j-api + + com.microsoft.azure.cognitiveservices + azure-cognitiveservices-luis-runtime + 1.0.2-beta + + com.microsoft.bot bot-builder diff --git a/libraries/bot-applicationinsights/pom.xml b/libraries/bot-applicationinsights/pom.xml index 75e27215b..250c78c45 100644 --- a/libraries/bot-applicationinsights/pom.xml +++ b/libraries/bot-applicationinsights/pom.xml @@ -50,12 +50,17 @@ junit junit - org.slf4j slf4j-api + + com.microsoft.azure + applicationinsights-core + 2.4.1 + + com.microsoft.bot bot-builder diff --git a/libraries/bot-dialogs/pom.xml b/libraries/bot-dialogs/pom.xml index 6ab351abb..8320a4b03 100644 --- a/libraries/bot-dialogs/pom.xml +++ b/libraries/bot-dialogs/pom.xml @@ -55,6 +55,17 @@ slf4j-api + + com.microsoft.azure + azure-documentdb + 2.4.1 + + + com.microsoft.azure + azure-storage-blob + 11.0.1 + + com.microsoft.bot bot-builder From 0c87793a51c07f82f75af89c13adb4da7bf79660 Mon Sep 17 00:00:00 2001 From: Tracy Boehrer Date: Fri, 30 Aug 2019 12:49:10 -0500 Subject: [PATCH 26/26] Removed Luis package dependency. --- libraries/bot-ai-luis-v3/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libraries/bot-ai-luis-v3/pom.xml b/libraries/bot-ai-luis-v3/pom.xml index 31dcbd210..85608ab78 100644 --- a/libraries/bot-ai-luis-v3/pom.xml +++ b/libraries/bot-ai-luis-v3/pom.xml @@ -55,12 +55,6 @@ slf4j-api - - com.microsoft.azure.cognitiveservices - azure-cognitiveservices-luis-runtime - 1.0.2-beta - - com.microsoft.bot bot-builder