Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit fa525c6

Browse files
authored
Sample 05.multi-turn-prompt (#927)
* Initial 05.multi-turn-prompt * Sample 05.multi-turn-prompt
1 parent fb991ab commit fa525c6

File tree

33 files changed

+1768
-77
lines changed

33 files changed

+1768
-77
lines changed

libraries/bot-dialogs/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
<dependency>
7171
<groupId>com.microsoft.bot</groupId>
7272
<artifactId>bot-builder</artifactId>
73-
<version>4.6.0-preview8</version>
73+
<version>${project.version}</version>
7474
</dependency>
7575
<dependency>
7676
<groupId>com.microsoft.bot</groupId>

libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Dialog.java

Lines changed: 110 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.fasterxml.jackson.annotation.JsonProperty;
88
import com.microsoft.bot.builder.BotTelemetryClient;
99
import com.microsoft.bot.builder.NullBotTelemetryClient;
10+
import com.microsoft.bot.builder.StatePropertyAccessor;
1011
import com.microsoft.bot.builder.TurnContext;
1112
import java.util.concurrent.CompletableFuture;
1213
import org.apache.commons.lang3.StringUtils;
@@ -15,11 +16,13 @@
1516
* Base class for all dialogs.
1617
*/
1718
public abstract class Dialog {
19+
1820
/**
19-
* A {@link DialogTurnResult} that indicates that the current dialog is
20-
* still active and waiting for input from the user next turn.
21+
* A {@link DialogTurnResult} that indicates that the current dialog is still active and waiting
22+
* for input from the user next turn.
2123
*/
22-
public static final DialogTurnResult END_OF_TURN = new DialogTurnResult(DialogTurnStatus.WAITING);
24+
public static final DialogTurnResult END_OF_TURN = new DialogTurnResult(
25+
DialogTurnStatus.WAITING);
2326

2427
@JsonIgnore
2528
private BotTelemetryClient telemetryClient;
@@ -29,6 +32,7 @@ public abstract class Dialog {
2932

3033
/**
3134
* Initializes a new instance of the Dialog class.
35+
*
3236
* @param dialogId The ID to assign to this dialog.
3337
*/
3438
public Dialog(String dialogId) {
@@ -38,6 +42,7 @@ public Dialog(String dialogId) {
3842

3943
/**
4044
* Gets id for the dialog.
45+
*
4146
* @return Id for the dialog.
4247
*/
4348
public String getId() {
@@ -49,6 +54,7 @@ public String getId() {
4954

5055
/**
5156
* Sets id for the dialog.
57+
*
5258
* @param withId Id for the dialog.
5359
*/
5460
public void setId(String withId) {
@@ -57,6 +63,7 @@ public void setId(String withId) {
5763

5864
/**
5965
* Gets the {@link BotTelemetryClient} to use for logging.
66+
*
6067
* @return The BotTelemetryClient to use for logging.
6168
*/
6269
public BotTelemetryClient getTelemetryClient() {
@@ -65,6 +72,7 @@ public BotTelemetryClient getTelemetryClient() {
6572

6673
/**
6774
* Sets the {@link BotTelemetryClient} to use for logging.
75+
*
6876
* @param withTelemetryClient The BotTelemetryClient to use for logging.
6977
*/
7078
public void setTelemetryClient(BotTelemetryClient withTelemetryClient) {
@@ -74,10 +82,9 @@ public void setTelemetryClient(BotTelemetryClient withTelemetryClient) {
7482
/**
7583
* Called when the dialog is started and pushed onto the dialog stack.
7684
*
77-
* @param dc The {@link DialogContext} for the current turn of
78-
* conversation.
79-
* @return If the task is successful, the result indicates whether the dialog is still
80-
* active after the turn has been processed by the dialog.
85+
* @param dc The {@link DialogContext} for the current turn of conversation.
86+
* @return If the task is successful, the result indicates whether the dialog is still active
87+
* after the turn has been processed by the dialog.
8188
*/
8289
public CompletableFuture<DialogTurnResult> beginDialog(DialogContext dc) {
8390
return beginDialog(dc, null);
@@ -86,25 +93,25 @@ public CompletableFuture<DialogTurnResult> beginDialog(DialogContext dc) {
8693
/**
8794
* Called when the dialog is started and pushed onto the dialog stack.
8895
*
89-
* @param dc The {@link DialogContext} for the current turn of
90-
* conversation.
96+
* @param dc The {@link DialogContext} for the current turn of conversation.
9197
* @param options Initial information to pass to the dialog.
92-
* @return If the task is successful, the result indicates whether the dialog is still
93-
* active after the turn has been processed by the dialog.
98+
* @return If the task is successful, the result indicates whether the dialog is still active
99+
* after the turn has been processed by the dialog.
94100
*/
95-
public abstract CompletableFuture<DialogTurnResult> beginDialog(DialogContext dc, Object options);
101+
public abstract CompletableFuture<DialogTurnResult> beginDialog(
102+
DialogContext dc, Object options
103+
);
96104

97105
/**
98-
* Called when the dialog is _continued_, where it is the active dialog and the
99-
* user replies with a new activity.
106+
* Called when the dialog is _continued_, where it is the active dialog and the user replies
107+
* with a new activity.
100108
*
101-
* <p>If this method is *not* overridden, the dialog automatically ends when the user replies.</p>
109+
* <p>If this method is *not* overridden, the dialog automatically ends when the user
110+
* replies.</p>
102111
*
103-
* @param dc The {@link DialogContext} for the current turn of
104-
* conversation.
105-
* @return If the task is successful, the result indicates whether the dialog is still
106-
* active after the turn has been processed by the dialog. The result may also contain a
107-
* return value.
112+
* @param dc The {@link DialogContext} for the current turn of conversation.
113+
* @return If the task is successful, the result indicates whether the dialog is still active
114+
* after the turn has been processed by the dialog. The result may also contain a return value.
108115
*/
109116
public CompletableFuture<DialogTurnResult> continueDialog(DialogContext dc) {
110117
// By default just end the current dialog.
@@ -115,16 +122,17 @@ public CompletableFuture<DialogTurnResult> continueDialog(DialogContext dc) {
115122
* Called when a child dialog completed this turn, returning control to this dialog.
116123
*
117124
* <p>Generally, the child dialog was started with a call to
118-
* {@link #beginDialog(DialogContext, Object)} However, if the
119-
* {@link DialogContext#replaceDialog(String)} method
120-
* is called, the logical child dialog may be different than the original.</p>
125+
* {@link #beginDialog(DialogContext, Object)} However, if the {@link
126+
* DialogContext#replaceDialog(String)} method is called, the logical child dialog may be
127+
* different than the original.</p>
121128
*
122-
* <p>If this method is *not* overridden, the dialog automatically ends when the user replies.</p>
129+
* <p>If this method is *not* overridden, the dialog automatically ends when the user
130+
* replies.</p>
123131
*
124-
* @param dc The dialog context for the current turn of the conversation.
132+
* @param dc The dialog context for the current turn of the conversation.
125133
* @param reason Reason why the dialog resumed.
126-
* @return If the task is successful, the result indicates whether this dialog is still
127-
* active after this dialog turn has been processed.
134+
* @return If the task is successful, the result indicates whether this dialog is still active
135+
* after this dialog turn has been processed.
128136
*/
129137
public CompletableFuture<DialogTurnResult> resumeDialog(DialogContext dc, DialogReason reason) {
130138
return resumeDialog(dc, reason, null);
@@ -134,51 +142,63 @@ public CompletableFuture<DialogTurnResult> resumeDialog(DialogContext dc, Dialog
134142
* Called when a child dialog completed this turn, returning control to this dialog.
135143
*
136144
* <p>Generally, the child dialog was started with a call to
137-
* {@link #beginDialog(DialogContext, Object)} However, if the
138-
* {@link DialogContext#replaceDialog(String, Object)} method
139-
* is called, the logical child dialog may be different than the original.</p>
145+
* {@link #beginDialog(DialogContext, Object)} However, if the {@link
146+
* DialogContext#replaceDialog(String, Object)} method is called, the logical child dialog may
147+
* be different than the original.</p>
140148
*
141-
* <p>If this method is *not* overridden, the dialog automatically ends when the user replies.</p>
149+
* <p>If this method is *not* overridden, the dialog automatically ends when the user
150+
* replies.</p>
142151
*
143-
* @param dc The dialog context for the current turn of the conversation.
152+
* @param dc The dialog context for the current turn of the conversation.
144153
* @param reason Reason why the dialog resumed.
145-
* @param result Optional, value returned from the dialog that was called. The type of the
146-
* value returned is dependent on the child dialog.
147-
* @return If the task is successful, the result indicates whether this dialog is still
148-
* active after this dialog turn has been processed.
154+
* @param result Optional, value returned from the dialog that was called. The type of the value
155+
* returned is dependent on the child dialog.
156+
* @return If the task is successful, the result indicates whether this dialog is still active
157+
* after this dialog turn has been processed.
149158
*/
150-
public CompletableFuture<DialogTurnResult> resumeDialog(DialogContext dc, DialogReason reason, Object result) {
159+
public CompletableFuture<DialogTurnResult> resumeDialog(
160+
DialogContext dc, DialogReason reason, Object result
161+
) {
151162
// By default just end the current dialog and return result to parent.
152163
return dc.endDialog(result);
153164
}
154165

155166
/**
156167
* Called when the dialog should re-prompt the user for input.
168+
*
157169
* @param turnContext The context object for this turn.
158-
* @param instance State information for this dialog.
170+
* @param instance State information for this dialog.
159171
* @return A CompletableFuture representing the asynchronous operation.
160172
*/
161-
public CompletableFuture<Void> repromptDialog(TurnContext turnContext, DialogInstance instance) {
173+
public CompletableFuture<Void> repromptDialog(
174+
TurnContext turnContext, DialogInstance instance
175+
) {
162176
// No-op by default
163177
return CompletableFuture.completedFuture(null);
164178
}
165179

166180
/**
167181
* Called when the dialog is ending.
182+
*
168183
* @param turnContext The context object for this turn.
169-
* @param instance State information associated with the instance of this dialog on the dialog stack.
170-
* @param reason Reason why the dialog ended.
184+
* @param instance State information associated with the instance of this dialog on the
185+
* dialog stack.
186+
* @param reason Reason why the dialog ended.
171187
* @return A CompletableFuture representing the asynchronous operation.
172188
*/
173-
public CompletableFuture<Void> endDialog(TurnContext turnContext, DialogInstance instance, DialogReason reason) {
189+
public CompletableFuture<Void> endDialog(
190+
TurnContext turnContext, DialogInstance instance, DialogReason reason
191+
) {
174192
// No-op by default
175193
return CompletableFuture.completedFuture(null);
176194
}
177195

178196
/**
179197
* Gets a unique String which represents the version of this dialog. If the version changes
180198
* between turns the dialog system will emit a DialogChanged event.
181-
* @return Unique String which should only change when dialog has changed in a way that should restart the dialog.
199+
*
200+
* @return Unique String which should only change when dialog has changed in a way that should
201+
* restart the dialog.
182202
*/
183203
@JsonIgnore
184204
public String getVersion() {
@@ -188,8 +208,9 @@ public String getVersion() {
188208
/**
189209
* Called when an event has been raised, using `DialogContext.emitEvent()`, by either the
190210
* current dialog or a dialog that the current dialog started.
211+
*
191212
* @param dc The dialog context for the current turn of conversation.
192-
* @param e The event being raised.
213+
* @param e The event being raised.
193214
* @return True if the event is handled by the current dialog and bubbling should stop.
194215
*/
195216
public CompletableFuture<Boolean> onDialogEvent(DialogContext dc, DialogEvent e) {
@@ -222,8 +243,9 @@ public CompletableFuture<Boolean> onDialogEvent(DialogContext dc, DialogEvent e)
222243
* dialogs from performing their default processing.</p>
223244
*
224245
* @param dc The dialog context for the current turn of conversation.
225-
* @param e The event being raised.
226-
* @return Whether the event is handled by the current dialog and further processing should stop.
246+
* @param e The event being raised.
247+
* @return Whether the event is handled by the current dialog and further processing should
248+
* stop.
227249
*/
228250
protected CompletableFuture<Boolean> onPreBubbleEvent(DialogContext dc, DialogEvent e) {
229251
return CompletableFuture.completedFuture(false);
@@ -232,22 +254,61 @@ protected CompletableFuture<Boolean> onPreBubbleEvent(DialogContext dc, DialogEv
232254
/**
233255
* Called after an event was bubbled to all parents and wasn't handled.
234256
*
235-
* <p>This is a good place to perform default processing logic for an event. Returning `true` will
257+
* <p>This is a good place to perform default processing logic for an event. Returning `true`
258+
* will
236259
* prevent any processing of the event by child dialogs.</p>
237260
*
238261
* @param dc The dialog context for the current turn of conversation.
239-
* @param e The event being raised.
240-
* @return Whether the event is handled by the current dialog and further processing should stop.
262+
* @param e The event being raised.
263+
* @return Whether the event is handled by the current dialog and further processing should
264+
* stop.
241265
*/
242266
protected CompletableFuture<Boolean> onPostBubbleEvent(DialogContext dc, DialogEvent e) {
243267
return CompletableFuture.completedFuture(false);
244268
}
245269

246270
/**
247271
* Computes an id for the Dialog.
272+
*
248273
* @return The id.
249274
*/
250275
protected String onComputeId() {
251276
return this.getClass().getName();
252277
}
278+
279+
/**
280+
* Creates a dialog stack and starts a dialog, pushing it onto the stack.
281+
*
282+
* @param dialog The dialog to start.
283+
* @param turnContext The context for the current turn of the conversation.
284+
* @param accessor The StatePropertyAccessor accessor with which to manage the state of the
285+
* dialog stack.
286+
* @return A Task representing the asynchronous operation.
287+
*/
288+
public static CompletableFuture<Void> run(
289+
Dialog dialog,
290+
TurnContext turnContext,
291+
StatePropertyAccessor<DialogState> accessor
292+
) {
293+
DialogSet dialogSet = new DialogSet(accessor);
294+
dialogSet.add(dialog);
295+
dialogSet.setTelemetryClient(dialog.getTelemetryClient());
296+
297+
return dialogSet.createContext(turnContext)
298+
.thenCompose(dialogContext -> continueOrStart(dialogContext, dialog))
299+
.thenApply(result -> null);
300+
}
301+
302+
private static CompletableFuture<DialogTurnResult> continueOrStart(
303+
DialogContext dialogContext, Dialog dialog
304+
) {
305+
return dialogContext.continueDialog()
306+
.thenCompose(result -> {
307+
if (result.getStatus() == DialogTurnStatus.EMPTY) {
308+
return dialogContext.beginDialog(dialog.getId(), null);
309+
}
310+
311+
return CompletableFuture.completedFuture(result);
312+
});
313+
}
253314
}

libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/DialogContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public CompletableFuture<DialogTurnResult> beginDialog(String dialogId, Object o
200200
// Look up dialog
201201
Dialog dialog = findDialog(dialogId);
202202
if (dialog == null) {
203-
Async.completeExceptionally(new Exception(String.format(
203+
return Async.completeExceptionally(new Exception(String.format(
204204
"DialogContext.beginDialog(): A dialog with an id of '%s' wasn't found."
205205
+ " The dialog must be included in the current or parent DialogSet."
206206
+ " For example, if subclassing a ComponentDialog you can call AddDialog()"

libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/WaterfallDialog.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package com.microsoft.bot.dialogs;
55

66
import java.util.ArrayList;
7-
import java.util.Collection;
87
import java.util.HashMap;
98
import java.util.List;
109
import java.util.Map;
@@ -38,9 +37,9 @@ public class WaterfallDialog extends Dialog {
3837
* @param dialogId The dialog ID.
3938
* @param actions Optional actions to be defined by the caller.
4039
*/
41-
public WaterfallDialog(String dialogId, Collection<WaterfallStep> actions) {
40+
public WaterfallDialog(String dialogId, List<WaterfallStep> actions) {
4241
super(dialogId);
43-
steps = actions != null ? new ArrayList<WaterfallStep>(actions) : new ArrayList<WaterfallStep>();
42+
steps = actions != null ? actions : new ArrayList<WaterfallStep>();
4443
}
4544

4645
/**
@@ -126,7 +125,7 @@ public CompletableFuture<DialogTurnResult> continueDialog(DialogContext dc) {
126125
}
127126

128127
// Don't do anything for non-message activities.
129-
if (dc.getContext().getActivity().getType() != ActivityTypes.MESSAGE) {
128+
if (!dc.getContext().getActivity().isType(ActivityTypes.MESSAGE)) {
130129
return CompletableFuture.completedFuture(END_OF_TURN);
131130
}
132131

libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/choices/ChoiceFactory.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.microsoft.bot.schema.HeroCard;
1212
import com.microsoft.bot.schema.InputHints;
1313
import java.util.ArrayList;
14+
import java.util.Arrays;
1415
import java.util.List;
1516
import java.util.stream.Collectors;
1617
import org.apache.commons.lang3.StringUtils;
@@ -376,6 +377,16 @@ public static List<Choice> toChoices(List<String> choices) {
376377
return choices == null ? new ArrayList<>() : choices.stream().map(Choice::new).collect(Collectors.toList());
377378
}
378379

380+
/**
381+
* Returns a list of strings as a list of Choices.
382+
*
383+
* @param choices The strings to convert.
384+
* @return A List of Choices.
385+
*/
386+
public static List<Choice> toChoices(String... choices) {
387+
return toChoices(Arrays.asList(choices));
388+
}
389+
379390
private static List<CardAction> extractActions(List<Choice> choices) {
380391
if (choices == null) {
381392
choices = new ArrayList<>();

libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/prompts/AttachmentPrompt.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ protected CompletableFuture<PromptRecognizerResult<List<Attachment>>> onRecogniz
105105
}
106106

107107
PromptRecognizerResult<List<Attachment>> result = new PromptRecognizerResult<List<Attachment>>();
108-
if (turnContext.getActivity().getType() == ActivityTypes.MESSAGE) {
108+
if (turnContext.getActivity().isType(ActivityTypes.MESSAGE)) {
109109
Activity message = turnContext.getActivity();
110110
if (message.getAttachments() != null && message.getAttachments().size() > 0) {
111111
result.setSucceeded(true);

0 commit comments

Comments
 (0)