Added Event Factory for handoff protocol (#1118)

* Added Event Factory for handoff protocol

* Added additional unit test.

Co-authored-by: tracyboehrer <tracyboehrer@users.noreply.github.com>
This commit is contained in:
Lee Parrish 2021-04-01 09:42:40 -05:00 коммит произвёл GitHub
Родитель 42edeb37d3
Коммит 45130e6ae7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 297 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MT License.
package com.microsoft.bot.builder;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.UUID;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.microsoft.bot.schema.Activity;
import com.microsoft.bot.schema.Attachment;
import com.microsoft.bot.schema.ConversationAccount;
import com.microsoft.bot.schema.Entity;
import com.microsoft.bot.schema.HandoffEventNames;
import com.microsoft.bot.schema.Transcript;
import org.apache.commons.lang3.StringUtils;
/**
* Contains utility methods for creating various event types.
*/
public final class EventFactory {
private EventFactory() {
}
/**
* Create handoff initiation event.
*
* @param turnContext turn context.
* @param handoffContext agent hub-specific context.
*
* @return handoff event.
*/
public static Activity createHandoffInitiation(TurnContext turnContext, Object handoffContext) {
return createHandoffInitiation(turnContext, handoffContext, null);
}
/**
* Create handoff initiation event.
*
* @param turnContext turn context.
* @param handoffContext agent hub-specific context.
* @param transcript transcript of the conversation.
*
* @return handoff event.
*/
public static Activity createHandoffInitiation(TurnContext turnContext, Object handoffContext,
Transcript transcript) {
if (turnContext == null) {
throw new IllegalArgumentException("turnContext cannot be null.");
}
Activity handoffEvent = createHandoffEvent(HandoffEventNames.INITIATEHANDOFF, handoffContext,
turnContext.getActivity().getConversation());
handoffEvent.setFrom(turnContext.getActivity().getFrom());
handoffEvent.setRelatesTo(turnContext.getActivity().getConversationReference());
handoffEvent.setReplyToId(turnContext.getActivity().getId());
handoffEvent.setServiceUrl(turnContext.getActivity().getServiceUrl());
handoffEvent.setChannelId(turnContext.getActivity().getChannelId());
if (transcript != null) {
Attachment attachment = new Attachment();
attachment.setContent(transcript);
attachment.setContentType("application/json");
attachment.setName("Transcript");
handoffEvent.getAttachments().add(attachment);
}
return handoffEvent;
}
/**
* Create handoff status event.
*
* @param conversation Conversation being handed over.
* @param state State, possible values are: "accepted", "failed",
* "completed".
*
* @return handoff event.
*/
public static Activity createHandoffStatus(ConversationAccount conversation, String state) {
return createHandoffStatus(conversation, state, null);
}
/**
* Create handoff status event.
*
* @param conversation Conversation being handed over.
* @param state State, possible values are: "accepted", "failed",
* "completed".
* @param message Additional message for failed handoff.
*
* @return handoff event.
*/
public static Activity createHandoffStatus(ConversationAccount conversation, String state, String message) {
if (conversation == null) {
throw new IllegalArgumentException("conversation cannot be null.");
}
if (state == null) {
throw new IllegalArgumentException("state cannot be null.");
}
ObjectNode handoffContext = JsonNodeFactory.instance.objectNode();
handoffContext.set("state", JsonNodeFactory.instance.textNode(state));
if (StringUtils.isNotBlank(message)) {
handoffContext.set("message", JsonNodeFactory.instance.textNode(message));
}
Activity handoffEvent = createHandoffEvent(HandoffEventNames.HANDOFFSTATUS, handoffContext, conversation);
return handoffEvent;
}
private static Activity createHandoffEvent(String name, Object value, ConversationAccount conversation) {
Activity handoffEvent = Activity.createEventActivity();
handoffEvent.setName(name);
handoffEvent.setValue(value);
handoffEvent.setId(UUID.randomUUID().toString());
handoffEvent.setTimestamp(OffsetDateTime.now(ZoneId.of("UTC")));
handoffEvent.setConversation(conversation);
handoffEvent.setAttachments(new ArrayList<Attachment>());
handoffEvent.setEntities(new ArrayList<Entity>());
return handoffEvent;
}
}

Просмотреть файл

@ -0,0 +1,138 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MT License.
package com.microsoft.bot.builder;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.microsoft.bot.builder.adapters.TestAdapter;
import com.microsoft.bot.schema.Activity;
import com.microsoft.bot.schema.ActivityTypes;
import com.microsoft.bot.schema.ChannelAccount;
import com.microsoft.bot.schema.ConversationAccount;
import com.microsoft.bot.schema.HandoffEventNames;
import com.microsoft.bot.schema.Serialization;
import com.microsoft.bot.schema.Transcript;
import org.junit.Assert;
import org.junit.Test;
public class EventFactoryTests {
@Test
public void HandoffInitiationNullTurnContext() {
Assert.assertThrows(IllegalArgumentException.class,
() -> EventFactory.createHandoffInitiation(null, "some text"));
}
@Test
public void HandoffStatusNullConversation() {
Assert.assertThrows(IllegalArgumentException.class, () -> EventFactory.createHandoffStatus(null, "accepted"));
}
@Test
public void HandoffStatusNullStatus() {
Assert.assertThrows(IllegalArgumentException.class,
() -> EventFactory.createHandoffStatus(new ConversationAccount(), null));
}
@Test
public void TestCreateHandoffInitiation() {
TestAdapter adapter = new TestAdapter(
TestAdapter.createConversationReference("TestCreateHandoffInitiation", "User1", "Bot"));
String fromD = "test";
Activity activity = new Activity(ActivityTypes.MESSAGE);
activity.setText("");
activity.setConversation(new ConversationAccount());
activity.setRecipient(new ChannelAccount());
activity.setFrom(new ChannelAccount(fromD));
activity.setChannelId("testchannel");
activity.setServiceUrl("http://myservice");
TurnContext context = new TurnContextImpl(adapter, activity);
List<Activity> activities = new ArrayList<Activity>();
activities.add(MessageFactory.text("hello"));
Transcript transcript = new Transcript();
transcript.setActivities(activities);
Assert.assertNull(transcript.getActivities().get(0).getChannelId());
Assert.assertNull(transcript.getActivities().get(0).getServiceUrl());
Assert.assertNull(transcript.getActivities().get(0).getConversation());
ObjectNode handoffContext = JsonNodeFactory.instance.objectNode();
handoffContext.set("Skill", JsonNodeFactory.instance.textNode("any"));
Activity handoffEvent = EventFactory.createHandoffInitiation(context, handoffContext, transcript);
Assert.assertEquals(handoffEvent.getName(), HandoffEventNames.INITIATEHANDOFF);
ObjectNode node = (ObjectNode) handoffEvent.getValue();
String skill = node.get("Skill").asText();
Assert.assertEquals("any", skill);
Assert.assertEquals(handoffEvent.getFrom().getId(), fromD);
}
@Test
public void TestCreateHandoffInitiationNoTranscript() {
TestAdapter adapter = new TestAdapter(
TestAdapter.createConversationReference("TestCreateHandoffInitiation", "User1", "Bot"));
String fromD = "test";
Activity activity = new Activity(ActivityTypes.MESSAGE);
activity.setText("");
activity.setConversation(new ConversationAccount());
activity.setRecipient(new ChannelAccount());
activity.setFrom(new ChannelAccount(fromD));
activity.setChannelId("testchannel");
activity.setServiceUrl("http://myservice");
TurnContext context = new TurnContextImpl(adapter, activity);
List<Activity> activities = new ArrayList<Activity>();
activities.add(MessageFactory.text("hello"));
ObjectNode handoffContext = JsonNodeFactory.instance.objectNode();
handoffContext.set("Skill", JsonNodeFactory.instance.textNode("any"));
Activity handoffEvent = EventFactory.createHandoffInitiation(context, handoffContext);
Assert.assertEquals(handoffEvent.getName(), HandoffEventNames.INITIATEHANDOFF);
ObjectNode node = (ObjectNode) handoffEvent.getValue();
String skill = node.get("Skill").asText();
Assert.assertEquals("any", skill);
Assert.assertEquals(handoffEvent.getFrom().getId(), fromD);
}
@Test
public void TestCreateHandoffStatus() throws JsonProcessingException {
String state = "failed";
String message = "timed out";
Activity handoffEvent = EventFactory.createHandoffStatus(new ConversationAccount(), state, message);
Assert.assertEquals(handoffEvent.getName(), HandoffEventNames.HANDOFFSTATUS);
ObjectNode node = (ObjectNode) handoffEvent.getValue();
String stateFormEvent = node.get("state").asText();
Assert.assertEquals(stateFormEvent, state);
String messageFormEvent = node.get("message").asText();
Assert.assertEquals(messageFormEvent, message);
String status = Serialization.toString(node);
Assert.assertEquals(status, String.format("{\"state\":\"%s\",\"message\":\"%s\"}", state, message));
Assert.assertNotNull(handoffEvent.getAttachments());
Assert.assertNotNull(handoffEvent.getId());
}
@Test
public void TestCreateHandoffStatusNoMessage() {
String state = "failed";
Activity handoffEvent = EventFactory.createHandoffStatus(new ConversationAccount(), state);
ObjectNode node = (ObjectNode) handoffEvent.getValue();
String stateFormEvent = node.get("state").asText();
Assert.assertEquals(stateFormEvent, state);
JsonNode messageFormEvent = node.get("message");
Assert.assertNull(messageFormEvent);
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.bot.schema;
/**
* Defines values for handoff event names.
*/
public final class HandoffEventNames {
private HandoffEventNames() {
}
/**
* The value of handoff events for initiate handoff.
*/
public static final String INITIATEHANDOFF = "handoff.initiate";
/**
* The value of handoff events for handoff status.
*/
public static final String HANDOFFSTATUS = "handoff.status";
}