package org.infinispan.test.concurrent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeoutException;
import org.infinispan.Cache;
import org.infinispan.commands.ReplicableCommand;
import org.infinispan.interceptors.AsyncInterceptor;
import org.infinispan.manager.EmbeddedCacheManager;
/**
* Various helper methods for working with {@link StateSequencer}s.
*
* @author Dan Berindei
* @since 7.0
*/
public class StateSequencerUtil {
/**
* Start decorating interceptor {@code interceptorClass} on {@code cache} to interact with a {@code StateSequencer}.
*/
public static InterceptorSequencerAction advanceOnInterceptor(StateSequencer stateSequencer, Cache<?, ?> cache,
Class<? extends AsyncInterceptor> interceptorClass, CommandMatcher matcher) {
return new InterceptorSequencerAction(stateSequencer, cache, interceptorClass, matcher);
}
/**
* Start decorating the {@code InboundInvocationHandler} on {@code cacheManager} to interact with a {@code StateSequencer}
* when a {@code CacheRpcCommand} is received.
*/
public static InboundRpcSequencerAction advanceOnInboundRpc(StateSequencer stateSequencer, Cache cache,
CommandMatcher matcher) {
return new InboundRpcSequencerAction(stateSequencer, cache, matcher);
}
/**
* Start decorating the {@code RpcManager} on {@code cacheManager} to interact with a {@code StateSequencer} when a
* command is sent.
*/
public static OutboundRpcSequencerAction advanceOnOutboundRpc(StateSequencer stateSequencer, Cache<?, ?> cache,
CommandMatcher matcher) {
return new OutboundRpcSequencerAction(stateSequencer, cache, matcher);
}
/**
* Start decorating the component {@code componentClass} on {@code cache} to interact with a {@code StateSequencer} when a
* method is called.
*/
public static CacheComponentSequencerAction advanceOnComponentMethod(StateSequencer stateSequencer, Cache<?, ?> cache, Class<?> componentClass,
InvocationMatcher matcher) {
return new CacheComponentSequencerAction(stateSequencer, cache, componentClass, matcher);
}
/**
* Start decorating the component {@code componentClass} on {@code cacheManager} to interact with a {@code StateSequencer}
* when a method is called.
*/
public static <T> GlobalComponentSequencerAction advanceOnGlobalComponentMethod(StateSequencer stateSequencer,
EmbeddedCacheManager cacheManager, Class<T> componentClass, InvocationMatcher matcher) {
return new GlobalComponentSequencerAction(stateSequencer, cacheManager, componentClass, matcher);
}
/**
* Start building a {@link CommandMatcher}.
*/
public static CommandMatcherBuilder matchCommand(Class<? extends ReplicableCommand> commandClass) {
return new CommandMatcherBuilder(commandClass);
}
/**
* Start building a {@link InvocationMatcher}.
*/
public static InvocationMatcherBuilder matchMethodCall(String methodName) {
return new InvocationMatcherBuilder(methodName);
}
public static List<String> listCopy(List<String> statesUp) {
return statesUp != null ? Collections.unmodifiableList(new LinkedList<String>(statesUp)) : null;
}
public static List<String> concat(String state1, String... additionalStates) {
List<String> states = new ArrayList<String>();
states.add(state1);
if (additionalStates != null) {
states.addAll(Arrays.asList(additionalStates));
}
return states;
}
/**
* Advance to the every state in the {@code states} list, in the given order, but only if {@code condition} is true.
* <p/>
* Does nothing if {@code states} is {@code null} or empty.
*/
public static void advanceMultiple(StateSequencer stateSequencer, boolean condition, List<String> states)
throws TimeoutException, InterruptedException {
if (condition && states != null) {
for (String state : states) {
stateSequencer.advance(state);
}
}
}
}