package kernel; import rescuecore2.config.Config; import rescuecore2.messages.Command; import rescuecore2.log.Logger; import java.util.Collection; import java.util.Set; import java.util.HashSet; import java.util.Iterator; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.Executors; import java.util.concurrent.ExecutionException; /** A CommandCollector that waits for any of a set of child CommandCollectors to return a result. */ public class CompositeCommandCollector implements CommandCollector { private Set<CommandCollector> children; /** Construct a CompositeCommandCollector with no children. */ public CompositeCommandCollector() { children = new HashSet<CommandCollector>(); } @Override public void initialise(Config config) { for (CommandCollector next : children) { next.initialise(config); } } @Override public Collection<Command> getAgentCommands(Collection<AgentProxy> agents, int timestep) throws InterruptedException { if (agents.size() == 0) { return new HashSet<Command>(); } ExecutorCompletionService<Collection<Command>> service = new ExecutorCompletionService<Collection<Command>>(Executors.newFixedThreadPool(agents.size())); Set<Future<Collection<Command>>> futures = new HashSet<Future<Collection<Command>>>(); for (CommandCollector next : children) { futures.add(service.submit(new ChildCommandsFetcher(next, agents, timestep))); } try { int size = children.size(); for (int i = 0; i < size; ++i) { try { return service.take().get(); } catch (ExecutionException e) { Logger.error("Error while getting agent commands", e); } } } finally { for (Future<Collection<Command>> next : futures) { next.cancel(true); } } return new HashSet<Command>(); } /** Add a child command collector. @param child The child to add. */ public void addCommandCollector(CommandCollector child) { children.add(child); } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("CompositeCommandCollector ["); for (Iterator<CommandCollector> it = children.iterator(); it.hasNext();) { result.append(it.next()); if (it.hasNext()) { result.append(", "); } } result.append("]"); return result.toString(); } private static final class ChildCommandsFetcher implements Callable<Collection<Command>> { private CommandCollector child; private Collection<AgentProxy> agents; private int timestep; ChildCommandsFetcher(CommandCollector child, Collection<AgentProxy> agents, int timestep) { this.child = child; this.agents = agents; this.timestep = timestep; } @Override public Collection<Command> call() throws Exception { return child.getAgentCommands(agents, timestep); } } }