package org.infinispan.interceptors; import java.util.List; import java.util.concurrent.CompletableFuture; import org.infinispan.commands.VisitableCommand; import org.infinispan.commons.util.Experimental; import org.infinispan.context.InvocationContext; /** * Interceptor chain using {@link AsyncInterceptor}s. * * Experimental: The ability to modify the interceptors at runtime may be removed in future versions. * * @author Dan Berindei * @since 9.0 */ @Experimental public interface AsyncInterceptorChain { /** * @return An immutable list of the current interceptors. */ List<AsyncInterceptor> getInterceptors(); /** * Inserts the given interceptor at the specified position in the chain (0 based indexing). * * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are only 2 interceptors * in the chain) */ void addInterceptor(AsyncInterceptor interceptor, int position); /** * Removes the interceptor at the given position. * * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are only 2 interceptors * in the chain) */ void removeInterceptor(int position); /** * Returns the number of interceptors in the chain. */ int size(); /** * Removes all the occurrences of supplied interceptor type from the chain. */ void removeInterceptor(Class<? extends AsyncInterceptor> clazz); /** * Adds a new interceptor in list after an interceptor of a given type. * * @return true if the interceptor was added; i.e. the {@code afterInterceptor} exists */ boolean addInterceptorAfter(AsyncInterceptor toAdd, Class<? extends AsyncInterceptor> afterInterceptor); /** * Adds a new interceptor in list before an interceptor of a given type. * * @return true if the interceptor was added; i.e. the {@code beforeInterceptor} exists */ boolean addInterceptorBefore(AsyncInterceptor toAdd, Class<? extends AsyncInterceptor> beforeInterceptor); /** * Replaces an existing interceptor of the given type in the interceptor chain with a new interceptor * instance passed as parameter. * * @param replacingInterceptor the interceptor to add to the interceptor chain * @param toBeReplacedInterceptorType the type of interceptor that should be swapped with the new one * @return true if the interceptor was replaced */ boolean replaceInterceptor(AsyncInterceptor replacingInterceptor, Class<? extends AsyncInterceptor> toBeReplacedInterceptorType); /** * Appends at the end. */ void appendInterceptor(AsyncInterceptor ci, boolean isCustom); /** * Walks the command through the interceptor chain. The received ctx is being passed in. * * <p>Note: Reusing the context for multiple invocations is allowed, however most context implementations are not * thread-safe.</p> */ Object invoke(InvocationContext ctx, VisitableCommand command); /** * Walks the command through the interceptor chain. The received ctx is being passed in. */ CompletableFuture<Object> invokeAsync(InvocationContext ctx, VisitableCommand command); /** * Returns the first interceptor extending the given class, or {@code null} if there is none. */ <T extends AsyncInterceptor> T findInterceptorExtending(Class<T> interceptorClass); /** * Returns the first interceptor with the given class, or {@code null} if there is none. */ <T extends AsyncInterceptor> T findInterceptorWithClass(Class<T> interceptorClass); /** * Checks whether the chain contains the supplied interceptor instance. */ boolean containsInstance(AsyncInterceptor interceptor); /** * Checks whether the chain contains an interceptor with the given class. */ boolean containsInterceptorType(Class<? extends AsyncInterceptor> interceptorType); /** * Checks whether the chain contains an interceptor with the given class, or a subclass. */ boolean containsInterceptorType(Class<? extends AsyncInterceptor> interceptorType, boolean alsoMatchSubClasses); }