package org.infinispan.interceptors.impl; import java.util.Iterator; import org.infinispan.commands.VisitableCommand; import org.infinispan.context.InvocationContext; import org.infinispan.interceptors.BaseAsyncInterceptor; import org.infinispan.interceptors.InvocationSuccessFunction; /** * Invoke a sequence of sub-commands. * * @author Dan Berindei * @since 9.0 */ public class MultiSubCommandInvoker implements InvocationSuccessFunction { private final BaseAsyncInterceptor interceptor; private final Object finalStage; private final Iterator<VisitableCommand> subCommands; private MultiSubCommandInvoker(BaseAsyncInterceptor interceptor, Object finalReturnValue, Iterator<VisitableCommand> subCommands) { this.interceptor = interceptor; this.finalStage = finalReturnValue; this.subCommands = subCommands; } /** * Call {@link BaseAsyncInterceptor#invokeNext(InvocationContext, VisitableCommand)} on a sequence of sub-commands. * <p> * Stop when one of the sub-commands throws an exception, and return an invocation stage with that exception. If all * the sub-commands are successful, return the {@code finalStage}. If {@code finalStage} has and exception, skip all * the sub-commands and just return the {@code finalStage}. */ public static Object invokeEach(InvocationContext ctx, Iterator<VisitableCommand> subCommands, BaseAsyncInterceptor interceptor, Object finalReturnValue) { if (!subCommands.hasNext()) return finalReturnValue; MultiSubCommandInvoker invoker = new MultiSubCommandInvoker(interceptor, finalReturnValue, subCommands); VisitableCommand newCommand = subCommands.next(); return interceptor.invokeNextThenApply(ctx, newCommand, invoker); } @Override public Object apply(InvocationContext rCtx, VisitableCommand rCommand, Object rv) throws Throwable { if (subCommands.hasNext()) { VisitableCommand newCommand = subCommands.next(); return interceptor.invokeNext(rCtx, newCommand); } else { return finalStage; } } }