package dk.statsbiblioteket.medieplatform.autonomous.iterator.eventhandlers;
import dk.statsbiblioteket.medieplatform.autonomous.ResultCollector;
import dk.statsbiblioteket.medieplatform.autonomous.iterator.common.NodeBeginsParsingEvent;
import dk.statsbiblioteket.medieplatform.autonomous.iterator.common.NodeEndParsingEvent;
import dk.statsbiblioteket.medieplatform.autonomous.iterator.common.ParsingEvent;
import dk.statsbiblioteket.medieplatform.autonomous.iterator.common.TreeIterator;
import dk.statsbiblioteket.util.Strings;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
public class MultiThreadedEventRunner extends EventRunner {
private final EventCondition forker;
private final ExecutorService executor;
private List<Future<?>> childTasks = new ArrayList<>();
public MultiThreadedEventRunner(TreeIterator iterator, List<TreeEventHandler> eventHandlers,
ResultCollector resultCollector, EventCondition forker, ExecutorService executor) {
super(iterator, eventHandlers, resultCollector);
this.forker = forker;
this.executor = executor;
}
@Override
public void handleFinish() {
super.handleFinish();
}
@Override
public void handleNodeBegins(NodeBeginsParsingEvent current) {
if (forker.shouldFork(current)) {
//any further will spawn sub iterators
//Skip to next sibling will branch of the iterator that began with this node begins
//It will then return than iterator.
//And the iterator where this was called will skip to the next node begins that was not this tree
TreeIterator childIterator = iterator.skipToNextSibling();
EventRunner childRunner = new EventRunner(childIterator,eventHandlers,resultCollector,true);
Future<?> future = executor.submit(childRunner);
childTasks.add(future);
} else {
super.handleNodeBegins(current);
}
}
@Override
public void handleNodeEnd(NodeEndParsingEvent current) {
if (forker.shouldJoin(current)) {
for (Future<?> childTask : childTasks) {
try {
childTask.get();
} catch (InterruptedException | ExecutionException e) {
resultCollector.addFailure(current.getName(), EventRunner.EXCEPTION,
this.getClass().getSimpleName(), EventRunner.UNEXPECTED_ERROR + e.toString(),
Strings.getStackTrace(e));
}
}
}
super.handleNodeEnd(current);
}
public interface EventCondition{
public boolean shouldFork(ParsingEvent nodeBeginsParsingEvent);
public boolean shouldJoin(ParsingEvent nodeEndParsingEvent);
}
public static EventCondition singleThreaded = new EventCondition() {
@Override
public boolean shouldFork(ParsingEvent nodeBeginsParsingEvent) {
return false;
}
@Override
public boolean shouldJoin(ParsingEvent nodeEndParsingEvent) {
return false;
}
};
}