com.github.triceo.splitlog.expectations.AbstractExpectationManager Maven / Gradle / Ivy
Show all versions of splitlog-core Show documentation
package com.github.triceo.splitlog.expectations;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import com.github.triceo.splitlog.api.Message;
import com.github.triceo.splitlog.api.MessageAction;
import com.github.triceo.splitlog.api.MessageConsumer;
import com.github.triceo.splitlog.api.MessageDeliveryStatus;
import com.github.triceo.splitlog.api.MessageProducer;
import com.github.triceo.splitlog.logging.SplitlogLoggerFactory;
import com.github.triceo.splitlog.util.SplitlogThreadFactory;
/**
* Tracks expectations that are currently active for a given message consumer.
*
* @param
* The source for the messages.
* @param
* The type of condition that the expectations accept.
*/
abstract class AbstractExpectationManager, C> implements MessageConsumer
{
private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(new SplitlogThreadFactory(
"expectations"));
private static final Logger LOGGER = SplitlogLoggerFactory.getLogger(AbstractExpectationManager.class);
private final ConcurrentMap, Future> expectations = new ConcurrentHashMap, Future>();
private boolean isStopped = false;
protected abstract AbstractExpectation createExpectation(final C condition, final MessageAction action);
@Override
public boolean isStopped() {
return this.isStopped;
}
@Override
public synchronized void
messageReceived(final Message message, final MessageDeliveryStatus status, final P producer) {
if (this.isStopped()) {
throw new IllegalStateException("Already stopped.");
}
for (final AbstractExpectation exchange : this.expectations.keySet()) {
exchange.messageReceived(message, status, producer);
}
}
/**
* The resulting future will only return after such a message is received
* that makes the condition true.
*
* @param condition
* Condition to be true.
* @return The future.
*/
public synchronized Future setExpectation(final C condition) {
return this.setExpectation(condition, null);
}
/**
* The resulting future will only return after such a message is received
* that makes the condition true.
*
* @param condition
* Condition to be true.
* @return The future.
*/
public synchronized Future setExpectation(final C condition, final MessageAction action) {
if (this.isStopped()) {
throw new IllegalStateException("Already stopped.");
}
final AbstractExpectation expectation = this.createExpectation(condition, action);
final Future future = AbstractExpectationManager.EXECUTOR.submit(expectation);
this.expectations.put(expectation, future);
AbstractExpectationManager.LOGGER.info("Registered expectation {} with action {}.", expectation, action);
return future;
}
@Override
public synchronized boolean stop() {
if (this.isStopped()) {
return false;
}
this.isStopped = true;
for (final Future future : this.expectations.values()) {
future.cancel(true);
}
this.expectations.clear();
return true;
}
/**
* Stop tracking this expectation. Calls from the internal code only.
*
* @param expectation
* The expectation to stop.
* @return If stopped, false if stopped already.
*/
protected synchronized boolean unsetExpectation(final AbstractExpectation expectation) {
if (this.expectations.containsKey(expectation)) {
this.expectations.remove(expectation);
AbstractExpectationManager.LOGGER.info("Unregistered expectation {}.", expectation);
return true;
}
return false;
}
}