diff --git a/README.md b/README.md index 9b02846364a..187b08f8c35 100644 --- a/README.md +++ b/README.md @@ -250,10 +250,10 @@ System.out.println(result); ``` ### Conversation -Use the experimental [Conversation][conversation] service to identify intents, entities, and conduct conversations. +Use the [Conversation][conversation] service to identify intents, entities, and conduct conversations. ```java -ConversationService service = new ConversationService(ConversationService.VERSION_DATE_2016_05_19); +ConversationService service = new ConversationService(ConversationService.VERSION_DATE_2016_07_11); service.setUsernameAndPassword("", ""); MessageRequest newMessage = new MessageRequest.Builder().inputText("Hi").build(); diff --git a/examples/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationExample.java b/examples/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationExample.java new file mode 100644 index 00000000000..effaa9945e6 --- /dev/null +++ b/examples/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationExample.java @@ -0,0 +1,85 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1; + +import java.util.Map; + +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse; +import com.ibm.watson.developer_cloud.http.ServiceCallback; + +import jersey.repackaged.jsr166e.CompletableFuture; + +/** + * Example of how to call the {@link ConversationService#message(String, MessageRequest)} method + * synchronous, asynchronous, and using react. + * @version v1-experimental + */ +public class ConversationExample { + + public static void main(String[] args) throws Exception { + ConversationService service = new ConversationService(ConversationService.VERSION_DATE_2016_07_11); + service.setUsernameAndPassword("", ""); + + // sync + MessageRequest newMessage = new MessageRequest.Builder().inputText("Hi").build(); + MessageResponse response = service.message("", newMessage).execute(); + System.out.println(response); + + + // async + service.message("", newMessage).enqueue(new ServiceCallback() { + @Override + public void onResponse(MessageResponse response) { + System.out.println(response); + } + + @Override + public void onFailure(Exception e) {} + }); + + // rx callback + service.message("", newMessage).rx() + .thenApply(new CompletableFuture.Fun>() { + @Override + public Map apply(MessageResponse message) { + return message.getOutput(); + } + }).thenAccept(new CompletableFuture.Action>() { + @Override + public void accept(Map output) { + System.out.println(output); + } + }); + + // rx async callback + service.message("", newMessage).rx() + .thenApplyAsync(new CompletableFuture.Fun>() { + @Override + public Map apply(MessageResponse message) { + return message.getOutput(); + } + }).thenAccept(new CompletableFuture.Action>() { + @Override + public void accept(Map output) { + System.out.println(output); + } + }); + + // rx sync + MessageResponse rxMessageResponse = service.message("", newMessage).rx().get(); + System.out.println(rxMessageResponse); + } + +} diff --git a/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationService.java b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationService.java new file mode 100644 index 00000000000..7fd06ac597c --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationService.java @@ -0,0 +1,89 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1; + +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse; +import com.ibm.watson.developer_cloud.http.RequestBuilder; +import com.ibm.watson.developer_cloud.http.ServiceCall; +import com.ibm.watson.developer_cloud.service.WatsonService; +import com.ibm.watson.developer_cloud.util.GsonSingleton; +import com.ibm.watson.developer_cloud.util.ResponseConverterUtils; +import com.ibm.watson.developer_cloud.util.Validator; + +/** + * Thin wrapper around the Conversation Service REST API. + * + * @version v1 + * @see + * Conversation + * @api.version_date 2016-07-11 + */ +public final class ConversationService extends WatsonService { + + /** The Constant VERSION_DATE_2016-07-11. */ + public static final String VERSION_DATE_2016_07_11 = "2016-07-11"; + private static final String URL = "https://gateway.watsonplatform.net/conversation/api"; + private static final String SERVICE_NAME = "conversation"; + private static final String PATH_MESSAGE = "/v1/workspaces/%s/message"; + private static final String VERSION_PARAM = "version"; + private final String versionDate; + + + /** + * Returns an instance of the Conversation Service using the service's default endpoint (URL). + * + * @param versionDate Version of the API which is to be invoked by the REST client. + */ + public ConversationService(final String versionDate) { + super(SERVICE_NAME); + if (getEndPoint() == null || getEndPoint().isEmpty()) + setEndPoint(URL); + + Validator.isTrue(versionDate != null && !versionDate.isEmpty(), + "'version cannot be null. Use " + VERSION_DATE_2016_07_11); + this.versionDate = versionDate; + } + + /** + * Returns an instance of the Conversation Service using the service's default endpoint (URL), username and password. + * @param versionDate Version of the API which is to be invoked by the REST client. + * @param username the username + * @param password the password + */ + public ConversationService(final String versionDate, String username, String password) { + this(versionDate); + setUsernameAndPassword(username, password); + } + + /** + * Sends a message to the service through a {@link MessageRequest}. + * + * @param workspaceId the workspace id + * @param request the request + * @return The response for the given message. + */ + public ServiceCall message(String workspaceId, MessageRequest request) { + Validator.isTrue(workspaceId != null && !workspaceId.isEmpty(), "'workspaceId' cannot be null or empty"); + Validator.notNull(request, "'request' cannot be null"); + Validator.isTrue(request.input() != null && !request.input().isEmpty(), "'request.input' cannot be null or empty"); + + RequestBuilder builder = RequestBuilder.post(String.format(PATH_MESSAGE, workspaceId)); + builder.query(VERSION_PARAM, this.versionDate); + builder.bodyJson(GsonSingleton.getGson().toJsonTree(request).getAsJsonObject()); + return createServiceCall(builder.build(), ResponseConverterUtils.getObject(MessageResponse.class)); + } + +} diff --git a/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageRequest.java b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageRequest.java new file mode 100644 index 00000000000..e6a3600e84c --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageRequest.java @@ -0,0 +1,204 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1.model; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.annotations.SerializedName; +import com.ibm.watson.developer_cloud.conversation.v1.ConversationService; +import com.ibm.watson.developer_cloud.service.model.GenericModel; + +/** + * Object that represents the input and context of a conversation. This is used by the + * {@link ConversationService#message(String, MessageRequest)} method + * + * @see http://www.ibm.com/ + * watson/developercloud/conversation.html + * + */ +public class MessageRequest extends GenericModel { + + /** + * The Class Builder. + */ + public static class Builder { + private static final String TEXT = "text"; + private Map context; + private Map input; + private Boolean alternateIntents; + + /** + * Instantiates a new Builder. + */ + public Builder() {} + + /** + * Instantiates a new builder. + * + * @param messageRequest the message request + */ + private Builder(MessageRequest messageRequest) { + this.input = new HashMap(messageRequest.input); + this.context = new HashMap(messageRequest.context); + this.alternateIntents = messageRequest.alternateIntents; + } + + /** + * Generates a new {@link MessageRequest} object. It will contain the parameters set in the + * builder. + * + * @return a {@link MessageRequest} instance + */ + public MessageRequest build() { + return new MessageRequest(this); + } + + /** + * Sets the context/state which is to be sent to the message API as a part of the service + * request. Each response from the message API returns a context object which + * represents the state as defined by the service. The state is not maintained by the service, + * so the client must keep the state from each API call, and pass that state in as a part of any + * subsequent requests. + * + * @param context a map containing key value pairs representing the state/context of the + * conversation + * + * @return a builder object + */ + public Builder context(final Map context) { + this.context = context != null ? new HashMap(context) : context; + return this; + } + + /** + * Sets the alternate intents flag. Set to true to return all matching intents + * + * @param alternateIntents the alternate intents flag + * @return a builder object + */ + public Builder alternateIntents(final Boolean alternateIntents) { + this.alternateIntents = alternateIntents; + return this; + } + + /** + * Sets the input which is to be sent to the message API as a part of the service request. + * Typically the input will contain a text property (key and value). The + * text property is generally interpreted as being the user/system input which the + * service must parse for intents, entities etc..
+ * In advanced cases the client may pass in more than just text as a part of the service input. + * For the majority of cases calling the {@link #inputText(String)} method is sufficient to send + * text to the service on behalf of the user/system. + * + * @param input a map of properties to be sent to the service under the input property + * @return a builder object + */ + public Builder input(Map input) { + this.input = input != null ? new HashMap(input) : null; + return this; + } + + /** + * Sets the input text which is to be sent to the message API as a part of the service request. + * + * @param text the textual value to be assigned to the 'text' property on the input object. + * @return a builder object + */ + public Builder inputText(String text) { + if (input == null) { + input = new HashMap(); + } + input.put(TEXT, text); + return this; + } + } + + private Map context; + private Map input; + @SerializedName("alternate_intents") + private Boolean alternateIntents; + + /** + * Creates a new instance of the MessageRequest for the {@link ConversationService} service. + * Clients must use the {@link Builder} class to construct new instances of the class. + * + * @param options a builder configured with the various parameters for the request + */ + private MessageRequest(Builder options) { + this.context = options.context; + this.input = options.input; + this.alternateIntents = options.alternateIntents; + } + + /** + * Returns a map used to store context/state for the message API. Each response from the message + * API will return a context object as a part of the payload. This context must be maintained and + * passed in as a part of subsequent API calls. + * + * @return a map of properties + */ + public Map context() { + return context; + } + + /** + * Whether to return more than one intent. Set to true to return all matching intents boolean
+ * Default: false + * + * @return the boolean indicating if alternate intents should be returned + */ + public Boolean alternateIntents() { + return alternateIntents; + } + + + /** + * Returns a map storing the input which is to be sent to the service as a part of the API + * request. + * + * @return a map of properties + */ + public Map input() { + return input; + } + + + /** + * Convenience method which allows the developer to quickly retrieve the 'text' property from the + * input object. This is equivalent to calling: + * + *
+   * Map input = request.getInput();
+   * String text = null;
+   * if (input != null) {
+   *   text = input.get("text");
+   * }
+   * 
+ * + * @return the value of the input.text property + */ + public String inputText() { + return (input != null && input.get("text") != null) ? input.get("text").toString() : null; + } + + /** + * New builder. + * + * @return the builder + */ + public Builder newBuilder() { + return new Builder(this); + } +} diff --git a/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageResponse.java b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageResponse.java new file mode 100644 index 00000000000..99c34691a26 --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/MessageResponse.java @@ -0,0 +1,303 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1.model; + +import java.util.List; +import java.util.Map; + +import com.ibm.watson.developer_cloud.conversation.v1.ConversationService; +import com.ibm.watson.developer_cloud.service.model.GenericModel; +import com.ibm.watson.developer_cloud.util.RequestUtils; + +/** + * The response payload from the Conversation service's message API call + * {@link ConversationService#message(String, MessageRequest)}. + * + * @see http://www.ibm.com/ + * watson/developercloud/conversation.html + */ +public class MessageResponse extends GenericModel { + private static final String TEXT = "text"; + + /** + * An class used to describe the entity payload object. + */ + public static class Entity { + private String entity; + private Integer[] location; + private String value; + + /** + * Returns the name of the entity. e.g. "I'd like to get a pepperoni pizza", entity in this case + * would likely be "topping" (depending on how the system has been trained). The + * {@link #getValue()} of the input would be "pepperoni". + * + * @return the name of an entity + */ + public String getEntity() { + return entity; + } + + /** + * Returns the location of the entity within the input string, the array will have two values: a + * start index and end index. + * + * @return an array of locations (start and end) + */ + public Integer[] getLocation() { + return (location == null) ? null : location.clone(); + } + + /** + * Returns the detected value of the entity. + * + * @return a string representing the entity value + */ + public String getValue() { + return value; + } + + /** + * Sets the entity detected by the system for the given input. + * + * @param entity the new entity + */ + public void setEntity(String entity) { + this.entity = entity; + } + + /** + * Sets the location of the entity detected by the system (i.e. starting index and end index). + * + * @param location an array of Integers representing a start and end index + */ + public void setLocation(Integer... location) { + this.location = (location == null) ? null : location.clone(); + } + + /** + * Sets the value of the entity as detected by the system. + * + * @param value the new value + */ + public void setValue(String value) { + this.value = value; + } + } + + /** + * A class representing an Intent as detected by the service. The intent is the 'intent' of the + * user utterance, e.g. "pay_bill", "check_balance" etc.. The intent is accompanied by a + * confidence score ranging between 0.0 and 1.0, with 1.0 being the most confident. + */ + public static class Intent { + private Double confidence; + private String intent; + + /** + * Returns the confidence associated with the intent. When the service parses/analyzes the user + * input it tries to determine the 'intent' of what the user said. The service will be trained + * to expect n different intents and the service tries to match the input with one of the + * intents. The confidence is the value assigned by the system to the returned intent. High + * confidence scores (close to 1.0) imply that the system is very confident that the user meant + * the returned intent. Low confidence scores indicate that the system is not confident in its + * response. + * + * @return a float representing system confidence + */ + public Double getConfidence() { + return confidence; + } + + /** + * Returns the name of the intent that the system detected in the user input. + * + * @return a string representing an intent name + */ + public String getIntent() { + return intent; + } + + /** + * Sets the system confidence in the intent. + * + * @param confidence a float between 0.0 and 1.0 + */ + public void setConfidence(Double confidence) { + this.confidence = confidence; + } + + /** + * Sets the name of the intent the system understood the user to have 'said'. + * + * @param intent a string representing one of the trained intents + */ + public void setIntent(String intent) { + this.intent = intent; + } + } + + private Map context; + private List entities; + private List intents; + private Map output; + private Map input; + + + /** + * Returns the context as returned by the service. At each step in the chat flow the conversation + * designer has the ability to add information to the chat context. The context is a map of key + * value pairs, with the values being any valid JSON objects/primitives. + * + * @return a map representing context/state + */ + public Map getContext() { + return context; + } + + /** + * Returns the list of entities as detected by the service. + * + * @return an array of {@link Entity} objects + */ + public List getEntities() { + return entities; + } + + /** + * Returns the list of intents as detected by the service. + * + * @return an array of {@link Intent} objects. + */ + public List getIntents() { + return intents; + } + + /** + * Returns the output as returned by the service, may be null. + * + * @return a map of objects representing the response from the Dialog portion of the service. + */ + public Map getOutput() { + return output; + } + + /** + * Sets the context as determined by the service. + * + * @param context a map of key value pairs + */ + public void setContext(Map context) { + this.context = context; + } + + /** + * Sets a list of entities as detected by the service. + * + * @param entities an array of entities + */ + public void setEntities(List entities) { + this.entities = entities; + } + + /** + * Sets a list of intents as detected by the service. + * + * @param intents an array of intents + */ + public void setIntents(List intents) { + this.intents = intents; + } + + /** + * Sets the output as returned by the service. + * + * @param output a map of outputs as defined by the conversation designer + */ + public void setOutput(Map output) { + this.output = output; + } + + /** + * A convenience method for getting the text property from the output object. This is equivalent + * to calling: + * + *
+   * List text = null;
+   * Map output = response.getOutput();
+   * if (output != null) {
+   *   text = (List) output.get("text");
+   * }
+   * 
+ * + * @return an array of strings which is to be displayed/returned to the end user + */ + @SuppressWarnings("unchecked") + public List getText() { + if (output != null && output.containsKey(TEXT)) { + List text = (List) output.get(TEXT); + if (text != null) { + return (List) text; + } + } + return null; + } + + /** + * A convenience method for getting the text property from the output object. The text property is + * an array of strings. This convenience class concatenates the array, separating each entry with + * the separator string. + * + * @param separator the separator + * @return a concatenation of the strings in the output array, with each string separated by the + * separator string + */ + public String getTextConcatenated(String separator) { + List outputText = getText(); + if (outputText != null) { + return RequestUtils.join(outputText, separator); + } + return null; + } + + /** + * Gets the input. + * + * @return the input + */ + public Map getInput() { + return input; + } + + /** + * Sets the input. + * + * @param input the input + */ + public void setInput(Map input) { + this.input = input; + } + + /** + * Gets the input text. + * + * @return the input text + */ + public String getInputText() { + if (this.input != null && this.input.containsKey(TEXT)) { + return this.input.get(TEXT).toString(); + } + return null; + } +} diff --git a/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/package-info.java b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/package-info.java new file mode 100644 index 00000000000..cd74b245a2d --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/model/package-info.java @@ -0,0 +1,5 @@ +/** + * Classes that map the HTTP service requests and responses into POJOs + */ +package com.ibm.watson.developer_cloud.conversation.v1.model; + diff --git a/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/package-info.java b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/package-info.java new file mode 100644 index 00000000000..85bfc398bcb --- /dev/null +++ b/src/main/java/com/ibm/watson/developer_cloud/conversation/v1/package-info.java @@ -0,0 +1,5 @@ +/** + * Conversation Service v1 + */ +package com.ibm.watson.developer_cloud.conversation.v1; + diff --git a/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationServiceIT.java b/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationServiceIT.java new file mode 100644 index 00000000000..a71e9bb7a7f --- /dev/null +++ b/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationServiceIT.java @@ -0,0 +1,107 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1; + +import static org.junit.Assert.assertNotNull; + +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.ibm.watson.developer_cloud.WatsonServiceTest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse; + +/** + * Integration test for the {@link ConversationService}. + */ +public class ConversationServiceIT extends WatsonServiceTest { + + private ConversationService service; + private String workspaceId; + + /* + * (non-Javadoc) + * + * @see com.ibm.watson.developer_cloud.WatsonServiceTest#setUp() + */ + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + workspaceId = getValidProperty("conversation.v1.workspace_id"); + String username = getValidProperty("conversation.v1.username"); + String password = getValidProperty("conversation.v1.password"); + + service = new ConversationService(ConversationService.VERSION_DATE_2016_07_11); + service.setEndPoint(getValidProperty("conversation.v1.url")); + service.setUsernameAndPassword(username, password); + service.setDefaultHeaders(getDefaultHeaders()); + } + + /** + * Test start a conversation without message. + */ + @Test(expected=IllegalArgumentException.class) + public void testStartAConversationWithoutMessage() { + service.message(workspaceId, null).execute(); + } + + /** + * Test send messages. + * + * @throws InterruptedException the interrupted exception + */ + @Test + public void testSendMessages() throws InterruptedException { + final String[] messages = new String[] {"turn ac on", "turn right", "no", "yes"}; + Map context = null; + for (final String message : messages) { + MessageRequest request = new MessageRequest.Builder().inputText(message).alternateIntents(true).context(context).build(); + MessageResponse response = service.message(workspaceId, request).execute(); + + assertMessageFromService(response); + context = response.getContext(); + Thread.sleep(500); + } + } + + /** + * Assert {@link MessageResponse} from service. + * + * @param message the message from the {@link ConversationService} + */ + private void assertMessageFromService(MessageResponse message) { + assertNotNull(message); + assertNotNull(message.getEntities()); + assertNotNull(message.getIntents()); + } + + /** + * Test message with nulls. + */ + @Test(expected = IllegalArgumentException.class) + public void testMessageWithNulls() { + service.message(null, null).execute(); + } + + /** + * Test to string. + */ + @Test + public void testToString() { + assertNotNull(service.toString()); + } +} diff --git a/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationTest.java b/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationTest.java new file mode 100644 index 00000000000..ecc2493d3ef --- /dev/null +++ b/src/test/java/com/ibm/watson/developer_cloud/conversation/v1/ConversationTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.ibm.watson.developer_cloud.conversation.v1; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Before; +import org.junit.Test; + +import com.ibm.watson.developer_cloud.WatsonServiceUnitTest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest; +import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse; +import com.ibm.watson.developer_cloud.http.HttpHeaders; + +import okhttp3.mockwebserver.RecordedRequest; + +/** + * Unit tests for the {@link ConversationService} + */ +public class ConversationTest extends WatsonServiceUnitTest { + private ConversationService service; + private static final String FIXTURE = "src/test/resources/conversation/conversation.json"; + private static final String WORKSPACE_ID = "123"; + private static final String PATH_MESSAGE = "/v1/workspaces/" + WORKSPACE_ID + "/message"; + private static final String EMPTY = ""; + private static final String VERSION = "version"; + + + /* + * (non-Javadoc) + * + * @see com.ibm.watson.developer_cloud.WatsonServiceTest#setUp() + */ + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + service = new ConversationService(ConversationService.VERSION_DATE_2016_07_11); + service.setApiKey(EMPTY); + service.setEndPoint(getMockWebServerUrl()); + + } + + /** + * Test send message. + * + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @Test + public void testSendMessage() throws IOException, InterruptedException { + String text = "I'd like to get insurance to for my home"; + + MessageResponse mockResponse = loadFixture(FIXTURE, MessageResponse.class); + server.enqueue(jsonResponse(mockResponse)); + + MessageRequest options = new MessageRequest.Builder().inputText(text).alternateIntents(true).build(); + + // execute first request + MessageResponse serviceResponse = service.message(WORKSPACE_ID, options).execute(); + + // first request + RecordedRequest request = server.takeRequest(); + + String path = StringUtils.join(PATH_MESSAGE, "?", VERSION, "=", ConversationService.VERSION_DATE_2016_07_11); + assertEquals(path, request.getPath()); + assertArrayEquals(new String[] {"Do you want to get a quote?"}, serviceResponse.getText().toArray(new String[0])); + assertEquals("Do you want to get a quote?", serviceResponse.getTextConcatenated(" ")); + assertEquals(request.getMethod(), "POST"); + assertNotNull(request.getHeader(HttpHeaders.AUTHORIZATION)); + assertEquals("{\"input\":{\"text\":\"I'd like to get insurance to for my home\"},\"alternate_intents\":true}", request.getBody().readUtf8()); + assertEquals(serviceResponse, mockResponse); + } +}