All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.bot.builder.core.MiddlewareSet Maven / Gradle / Ivy

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.bot.builder.core;

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static com.ea.async.Async.await;


public class MiddlewareSet implements Middleware
{
    public NextDelegate Next;

    private final ArrayList _middleware = new ArrayList();

    public MiddlewareSet Use(Middleware middleware)
    {
        BotAssert.MiddlewareNotNull(middleware);
        _middleware.add(middleware);
        return this;
    }

    public CompletableFuture ReceiveActivity(TurnContext context)
            throws ExecutionException, InterruptedException {
        // await ReceiveActivityInternal(context, null).ConfigureAwait(false);
        return ReceiveActivityInternal(context, null);
    }

    public  CompletableFuture OnTurn(TurnContext context, NextDelegate next)
            throws ExecutionException, InterruptedException {
        await(ReceiveActivityInternal(context, null));
        await(next.next());
        return CompletableFuture.completedFuture(null);
    }

    public CompletableFuture OnTurn(TurnContext context, CompletableFuture next)
            throws ExecutionException, InterruptedException {
        return null;
    }

    /// 
    /// Intended to be called from Bot, this method performs exactly the same as the
    /// standard ReceiveActivity, except that it runs a user-defined delegate returns 
    /// if all Middlware in the receive pipeline was run.
    /// 
    public CompletableFuture ReceiveActivityWithStatus(TurnContext context, TurnTask callback)
            throws ExecutionException, InterruptedException {
        return ReceiveActivityInternal(context, callback);
    }

    private CompletableFuture ReceiveActivityInternal(TurnContext context, TurnTask callback)
            throws ExecutionException, InterruptedException {
        return ReceiveActivityInternal(context, callback, 0);
    }
    private CompletableFuture ReceiveActivityInternal(TurnContext context, TurnTask callback, int nextMiddlewareIndex )
            throws ExecutionException, InterruptedException {
        // Check if we're at the end of the middleware list yet
        if(nextMiddlewareIndex == _middleware.size())
        {
            // If all the Middlware ran, the "leading edge" of the tree is now complete. 
            // This means it's time to run any developer specified callback. 
            // Once this callback is done, the "trailing edge" calls are then completed. This
            // allows code that looks like:
            //      Trace.TraceInformation("before");
            //      await next();
            //      Trace.TraceInformation("after"); 
            // to run as expected.

            // If a callback was provided invoke it now and return its task, otherwise just return the completed task
            if (callback == null)
                return CompletableFuture.completedFuture(null);
            else
                return callback.invoke(context);
        }

        // Get the next piece of middleware 
        Middleware nextMiddleware = _middleware.get(nextMiddlewareIndex);
        NextDelegate next = new NextDelegate() {
            public CompletableFuture next() throws ExecutionException, InterruptedException {
                return ReceiveActivityInternal(context, callback, nextMiddlewareIndex + 1);
            }
        };

        // Execute the next middleware passing a closure that will recurse back into this method at the next piece of middlware as the NextDelegate
        return nextMiddleware.OnTurn(
            context,
            next);
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy