Example usage for java.util Queue isEmpty

List of usage examples for java.util Queue isEmpty

Introduction

In this page you can find the example usage for java.util Queue isEmpty.

Prototype

boolean isEmpty();

Source Link

Document

Returns true if this collection contains no elements.

Usage

From source file:org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl.java

/**
 * {@inheritDoc}//from   w ww  .ja  va2 s  .c  o m
 */
@Override
public void applyDefaultValues(Component component) {
    if (component == null) {
        return;
    }

    View view = ViewLifecycle.getView();
    Object model = ViewLifecycle.getModel();

    @SuppressWarnings("unchecked")
    Queue<LifecycleElement> elementQueue = RecycleUtils.getInstance(LinkedList.class);
    elementQueue.offer(component);
    try {
        while (!elementQueue.isEmpty()) {
            LifecycleElement currentElement = elementQueue.poll();

            // if component is a data field apply default value
            if (currentElement instanceof DataField) {
                DataField dataField = ((DataField) currentElement);

                // need to make sure binding is initialized since this could be on a page we have not initialized yet
                dataField.getBindingInfo().setDefaults(view, dataField.getPropertyName());

                populateDefaultValueForField(model, dataField, dataField.getBindingInfo().getBindingPath());
            }

            elementQueue.addAll(ViewLifecycleUtils.getElementsForLifecycle(currentElement).values());
        }
    } finally {
        elementQueue.clear();
        RecycleUtils.recycle(elementQueue);
    }
}

From source file:com.mirth.connect.plugins.datapruner.DataPruner.java

@Override
public void run() {
    try {/*  w  ww  .java2 s.  c  om*/
        logger.debug("Executing pruner, started at "
                + new SimpleDateFormat("MM/dd/yyyy hh:mm aa").format(Calendar.getInstance().getTime()));

        if (pruneEvents) {
            pruneEvents();
        }

        String date = new SimpleDateFormat(MessageWriterFactory.ARCHIVE_DATE_PATTERN)
                .format(Calendar.getInstance().getTime());
        String archiveFolder = (archiveEnabled) ? archiverOptions.getRootFolder() + IOUtils.DIR_SEPARATOR + date
                : null;
        Queue<PrunerTask> taskQueue;

        try {
            taskQueue = buildTaskQueue();
        } catch (Exception e) {
            // the error should already be logged
            return;
        }

        logger.debug("Pruner task queue built, " + taskQueue.size() + " channels will be processed");

        Map<String, String> attributes = new HashMap<String, String>();
        if (taskQueue.isEmpty()) {
            attributes.put("No messages to prune.", "");
            eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT,
                    Level.INFORMATION, Outcome.SUCCESS, attributes));
        }

        while (!taskQueue.isEmpty()) {
            ThreadUtils.checkInterruptedStatus();
            PrunerTask task = taskQueue.poll();

            try {
                status.setCurrentChannelId(task.getChannelId());
                status.setCurrentChannelName(task.getChannelName());
                status.setTaskStartTime(Calendar.getInstance());

                PruneResult result = pruneChannel(task.getChannelId(), task.getChannelName(),
                        task.getMessageDateThreshold(), task.getContentDateThreshold(), archiveFolder,
                        task.isArchiveEnabled());

                status.getProcessedChannelIds().add(task.getChannelId());

                attributes.put("Channel ID", task.getChannelId());
                attributes.put("Channel Name", task.getChannelName());

                if (archiveEnabled && task.isArchiveEnabled()) {
                    attributes.put("Messages Archived", Long.toString(result.numMessagesArchived));
                }

                attributes.put("Messages Pruned", Long.toString(result.numMessagesPruned));
                attributes.put("Content Rows Pruned", Long.toString(result.numContentPruned));
                attributes.put("Time Elapsed", getTimeElapsed());
                eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT,
                        Level.INFORMATION, Outcome.SUCCESS, attributes));
            } catch (InterruptedException e) {
                throw e;
            } catch (Exception e) {
                status.getFailedChannelIds().add(task.getChannelId());

                attributes.put("channel", task.getChannelName());
                attributes.put("error", e.getMessage());
                attributes.put("trace", ExceptionUtils.getStackTrace(e));
                eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT,
                        Level.ERROR, Outcome.FAILURE, attributes));
                Throwable t = e;
                if (e instanceof DataPrunerException) {
                    t = e.getCause();
                }
                logger.error("Failed to prune messages for channel " + task.getChannelName() + " ("
                        + task.getChannelId() + ").", t);
            } finally {
                status.getPendingChannelIds().remove(task.getChannelId());
                status.setCurrentChannelId(null);
                status.setCurrentChannelName(null);
            }
        }

        logger.debug("Pruner job finished executing");
    } catch (InterruptedException e) {
        // We need to clear this thread's interrupted status, or else the EventController will fail to dispatch the event
        Thread.interrupted();
        ServerEvent event = new ServerEvent(serverId, DataPrunerService.PLUGINPOINT + " Halted");
        event.setLevel(Level.INFORMATION);
        event.setOutcome(Outcome.SUCCESS);
        eventController.dispatchEvent(event);
        logger.debug("Data Pruner halted");
    } catch (Throwable t) {
        logger.error("An error occurred while executing the data pruner", t);
    } finally {
        status.setEndTime(Calendar.getInstance());
        lastStatus = SerializationUtils.clone(status);
        running.set(false);
    }
}

From source file:com.comphenix.xp.parser.text.MobParser.java

@Override
public MobQuery parse(String text) throws ParsingException {

    Queue<String> tokens = getParameterQueue(text);

    ParsingException errorReason = null;

    List<Short> types = Utility.getElementList((Short) null);
    List<DamageCause> causes = Utility.getElementList((DamageCause) null);
    List<Integer> sizes = Utility.getElementList((Integer) null);
    List<SkeletonType> skeletons = Utility.getElementList((SkeletonType) null);

    try {// w w w.  j a  v a2 s .c om
        types = flatten(entityTypeParser.parse(tokens));
        causes = damageCauseParser.parse(tokens);
        sizes = mobSizeParser.parse(tokens);
        skeletons = skeletonParser.parse(tokens);

    } catch (ParsingException e) {
        // Try more
        errorReason = e;
    }

    // Scan all unused parameters for these options first
    List<Boolean> spawner = spawnerParser.parseAny(tokens);
    List<Boolean> baby = babyParser.parseAny(tokens);
    List<Boolean> tamed = tamedParser.parseAny(tokens);
    List<Boolean> player = playerParser.parseAny(tokens);
    List<Boolean> villaged = villagedParser.parseAny(tokens); // Zombies

    // If there are some tokens left, a problem occured
    if (!tokens.isEmpty()) {

        // Let the user know about the reason too
        if (errorReason != null)
            throw errorReason;
        else
            throw ParsingException.fromFormat("Unknown item tokens: %s", StringUtils.join(tokens, ", "));
    }

    return new MobQuery(types, causes, sizes, skeletons, spawner, baby, tamed, player, villaged);
}

From source file:playground.sergioo.ptsim2013.qnetsimengine.PTQLink.java

void makeVehicleAvailableToNextDriver(QVehicle veh, double now) {

    /*// ww w  .  j  a v a  2s. c  om
     * Insert waiting passengers into vehicle.
     */
    Id<Vehicle> vehicleId = veh.getId();
    Set<MobsimAgent> passengers = this.passengersWaitingForCars.get(vehicleId);
    if (passengers != null) {
        // Copy set of passengers since otherwise we would modify it concurrently.
        List<MobsimAgent> passengersToHandle = new ArrayList<MobsimAgent>(passengers);
        for (MobsimAgent passenger : passengersToHandle) {
            this.unregisterPassengerAgentWaitingForCar(passenger, vehicleId);
            this.insertPassengerIntoVehicle(passenger, vehicleId, now);
        }
    }

    /*
     * If the next driver is already waiting for the vehicle, check whether
     * all passengers are also there. If not, the driver is not inserted
     * into the vehicle and the vehicle does not depart.
     */
    final Queue<MobsimDriverAgent> driversWaitingForCar = driversWaitingForCars.get(veh.getId());
    final boolean thereIsDriverWaiting = driversWaitingForCar != null && !driversWaitingForCar.isEmpty();
    if (thereIsDriverWaiting) {
        MobsimDriverAgent driverWaitingForPassengers = driversWaitingForPassengers
                .get(driversWaitingForCar.element().getId());
        if (driverWaitingForPassengers != null)
            return;
    }

    /*
     * If there is a driver waiting for its vehicle, and this car is not currently already leaving again with the
     * same vehicle, put the new driver into the vehicle and let it depart.
     */
    if (thereIsDriverWaiting && veh.getDriver() == null) {
        // set agent as driver and then let the vehicle depart
        veh.setDriver(driversWaitingForCar.remove());
        if (driversWaitingForCar.isEmpty()) {
            final Queue<MobsimDriverAgent> r = driversWaitingForCars.remove(veh.getId());
            assert r == driversWaitingForCar;
        }
        removeParkedVehicle(veh.getId());
        this.letVehicleDepart(veh, now);
    }
}

From source file:com.baifendian.swordfish.common.utils.graph.Graph.java

/**
 *  topological ?//www . j  av a  2 s. c o m
 *
 * @return key ?, ? true, () false, value  topology sort
 */
private Map.Entry<Boolean, List<VK>> topologicalSortImpl() {
    List<VK> sort = new ArrayList<>();
    Queue<VK> zeroVertex = new LinkedList<>();
    Map<VK, Integer> indegrees = new HashMap<>();

    synchronized (this) {
        // ? vertex , ??
        for (Map.Entry<VK, VD> id2Vertex : vertices.entrySet()) {
            VK key = id2Vertex.getKey();
            int inDegree = getIndegree(key);

            if (inDegree == 0) {
                sort.add(key);
                zeroVertex.add(key);
            } else {
                indegrees.put(key, inDegree);
            }
        }

        //  topology ,  0 , ??
        while (!zeroVertex.isEmpty()) {
            VK key = zeroVertex.poll();
            Collection<VK> postNodes = getPostNode(key);

            for (VK postKey : postNodes) {
                int d = indegrees.getOrDefault(postKey, 0);

                if (d <= 1) {
                    sort.add(postKey);
                    indegrees.remove(postKey);
                    zeroVertex.add(postKey);
                } else {
                    indegrees.put(postKey, d - 1);
                }
            }
        }
    }

    // indegrees , , ?
    return new AbstractMap.SimpleEntry(indegrees.isEmpty(), sort);
}

From source file:org.amanzi.neo.services.impl.statistics.PropertyStatisticsService.java

protected void updatePropertyVault(final Node propertyVault, final PropertyVault vault)
        throws ServiceException {
    nodeService.updateProperty(propertyVault, statisticsNodeProperties.getClassProperty(),
            vault.getClassName());/*from w  w  w  .ja va2s .  c  o m*/

    int size = nodeService.getNodeProperty(propertyVault, getGeneralNodeProperties().getSizeProperty(),
            NumberUtils.INTEGER_ZERO, false);

    Map<Object, Integer> values = new HashMap<Object, Integer>(vault.getValuesMap());

    Queue<Integer> removedIndexes = new LinkedList<Integer>();
    Stack<Integer> processedIndex = new Stack<Integer>();

    if (size > 0) {
        for (int i = 0; i < size; i++) {
            Object property = nodeService.getNodeProperty(propertyVault,
                    statisticsNodeProperties.getValuePrefix() + i, null, true);

            Integer newCount = values.remove(property);
            if (newCount != null) {
                nodeService.updateProperty(propertyVault, statisticsNodeProperties.getCountPrefix() + i,
                        newCount);
            } else {
                removedIndexes.add(i);
            }
            processedIndex.add(i);
        }
    }

    // remove old values
    for (Integer index : removedIndexes) {
        nodeService.removeNodeProperty(propertyVault, statisticsNodeProperties.getValuePrefix() + index, false);
        nodeService.removeNodeProperty(propertyVault, statisticsNodeProperties.getCountPrefix() + index, false);
    }

    int counter = size;
    for (Entry<Object, Integer> statEntry : values.entrySet()) {
        counter = removedIndexes.isEmpty() ? counter : removedIndexes.remove();

        nodeService.updateProperty(propertyVault, statisticsNodeProperties.getValuePrefix() + counter,
                statEntry.getKey());
        nodeService.updateProperty(propertyVault, statisticsNodeProperties.getCountPrefix() + counter,
                statEntry.getValue());

        counter++;
    }

    for (Integer newIndex : removedIndexes) {
        int oldIndex = processedIndex.pop();
        nodeService.renameNodeProperty(propertyVault, statisticsNodeProperties.getValuePrefix() + oldIndex,
                statisticsNodeProperties.getValuePrefix() + newIndex, false);
        nodeService.renameNodeProperty(propertyVault, statisticsNodeProperties.getCountPrefix() + oldIndex,
                statisticsNodeProperties.getCountPrefix() + newIndex, false);
    }

    nodeService.updateProperty(propertyVault, getGeneralNodeProperties().getSizeProperty(), values.size());
    nodeService.updateProperty(propertyVault, statisticsNodeProperties.getDefaultValueProperty(),
            vault.getDefaultValue());
}

From source file:edu.umn.cs.spatialHadoop.nasa.StockQuadTree.java

/**
 * Constructs a stock quad tree for the given resolution
 * @param resolution//from  ww w  . j a v  a 2s . co m
 */
StockQuadTree(int resolution) {
    this.resolution = resolution;
    this.r = new int[resolution * resolution];
    final int[] z = new int[resolution * resolution];
    // The list of all nodes
    Vector<Node> nodes = new Vector<Node>();

    // Compute the Z-order of all values
    for (int i = 0; i < z.length; i++) {
        short x = (short) (i % resolution);
        short y = (short) (i / resolution);
        int zorder = AggregateQuadTree.computeZOrder(x, y);
        z[i] = zorder;
        r[i] = i;
    }

    // Sort ArrayToZOrder1200 by Z-Order and keep the original position of
    // each element by mirroring all swaps to ZOrderToArray1200
    new QuickSort().sort(new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            int temp;
            // Swap z-values (which are to be sorted)
            temp = z[i];
            z[i] = z[j];
            z[j] = temp;

            // Swap their relative positions in the other array
            temp = r[i];
            r[i] = r[j];
            r[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            return z[i] - z[j];
        }
    }, 0, z.length);

    // Construct the structure of the quad tree based on Z-values
    // Maximum number of values per node. Set it to a very small number to
    // construct as many levels as possible. Notice that when quad trees
    // are aggregated, a single value might become 366 values in the same pos.
    final int capacity = 100;
    Node root = new Node();
    root.startPosition = 0;
    root.endPosition = z.length;
    root.id = 1;
    Queue<Node> nodesToCheckForSplit = new ArrayDeque<Node>();
    nodesToCheckForSplit.add(root);
    int numOfSignificantBitsInTree = getNumOfSignificantBits(resolution * resolution - 1);
    if ((numOfSignificantBitsInTree & 1) == 1)
        numOfSignificantBitsInTree++; // Round to next even value
    int maxId = 0;
    while (!nodesToCheckForSplit.isEmpty()) {
        Node nodeToCheckForSplit = nodesToCheckForSplit.poll();
        boolean needsToSplit = nodeToCheckForSplit.getNumOfElements() > capacity;
        if (nodeToCheckForSplit.id > maxId)
            maxId = nodeToCheckForSplit.id;
        nodes.add(nodeToCheckForSplit);
        if (needsToSplit) {
            // Need to split
            // Determine split points based on the Z-order values of the first and
            // last elements in this node
            int depth = nodeToCheckForSplit.id == 0 ? 0
                    : (getNumOfSignificantBits(nodeToCheckForSplit.id - 1) / 2 + 1);
            depth = (getNumOfSignificantBits(nodeToCheckForSplit.id) - 1) / 2;
            int numOfSignificantBitsInNode = numOfSignificantBitsInTree - depth * 2;

            // Create four child nodes under this node
            int zOrderCommonBits = z[nodeToCheckForSplit.startPosition]
                    & (0xffffffff << numOfSignificantBitsInNode);
            int childStartPosition = nodeToCheckForSplit.startPosition;
            for (int iChild = 0; iChild < 4; iChild++) {
                int zOrderUpperBound = zOrderCommonBits + ((iChild + 1) << (numOfSignificantBitsInNode - 2));
                int childEndPosition = Arrays.binarySearch(z, childStartPosition,
                        nodeToCheckForSplit.endPosition, zOrderUpperBound);
                if (childEndPosition < 0)
                    childEndPosition = -(childEndPosition + 1);
                Node child = new Node();
                child.startPosition = childStartPosition;
                child.endPosition = childEndPosition;
                child.id = nodeToCheckForSplit.id * 4 + iChild;
                nodesToCheckForSplit.add(child);
                // Prepare for next iteration
                childStartPosition = childEndPosition;
            }
            if (childStartPosition != nodeToCheckForSplit.endPosition)
                throw new RuntimeException();
        }
    }
    // Convert nodes to column format for memory efficiency
    nodesID = new int[nodes.size()];
    nodesStartPosition = new int[nodes.size()];
    nodesEndPosition = new int[nodes.size()];

    for (int i = 0; i < nodes.size(); i++) {
        Node node = nodes.get(i);
        nodesID[i] = node.id;
        nodesStartPosition[i] = node.startPosition;
        nodesEndPosition[i] = node.endPosition;
    }
}

From source file:plaid.compilerjava.CompilerCore.java

public PackageRep buildPlaidPath(List<CompilationUnit> cus) throws Exception {
    //Build up a representation of plaidpath
    PackageRep plaidpath = new PackageRep("$TOPLEVEL$");
    Stack<File> directoryWorklist = new Stack<File>();
    for (String base : cc.getPlaidpath())
        handlePlaidPathEntry(base, plaidpath, directoryWorklist);

    //we want to remove the stuff we're trying to compile so that we don't make assumptions based on
    //the previous form of the source files
    //but also want a complete picture for resolving imports and thence QIs
    for (CompilationUnit c : cus) {
        String cPackage = c.getPackageString();
        for (Decl d : c.getDecls()) {
            String memberName = d.getName();
            if (plaidpath.memberExists(cPackage, memberName)) { //indicate that this is outdated and will be updated soon
                plaidpath.lookupMember(cPackage, memberName).startRecompilation();
            } else { //add shell for use in import resolution
                MemberRep newMem = null;
                if (d instanceof FieldDecl)
                    newMem = new FieldRep(memberName);
                else if (d instanceof MethodDecl)
                    newMem = new MethodRep(memberName);
                else if (d instanceof StateDecl)
                    newMem = new StateRep(memberName);
                else
                    throw new RuntimeException("New type of MemberRep not accounted for");

                //will be replaced later
                newMem.startRecompilation();
                plaidpath.addMember(cPackage, newMem);
            }//from  w ww.j  a v a 2s  .com

        }
    }

    Queue<StateRep> dependants = new LinkedList<StateRep>();
    for (CompilationUnit c : cus) {
        String cPackage = c.getPackageString();

        //expand imports
        List<String> declaredMembers = new ArrayList<String>(); //right now declared members are just those in the file, not the whole package
        for (Decl d : c.getDecls())
            declaredMembers.add(d.getName());
        c.getImports().checkAndExpandImports(plaidpath, declaredMembers, cPackage);

        //fill out plaidpath with declared members (shell info only)
        for (Decl d : c.getDecls()) {
            MemberRep rep = d.generateHeader(plaidpath, c.getImports(), cPackage);
            if (rep instanceof StateRep && ((StateRep) rep).hasNeeds()) {
                dependants.add((StateRep) rep); //keep track of ones we need to return to
            }
            plaidpath.addMember(cPackage, rep);
        }
    }

    while (!dependants.isEmpty()) {
        StateRep s = dependants.remove();
        List<String> newNeeds = new ArrayList<String>();
        for (String path : s.getNeeds()) {
            if (plaidpath.memberExists(path)) {
                MemberRep r = plaidpath.lookupMember(path);
                if (r instanceof StateRep) {
                    StateRep depState = (StateRep) r;
                    s.addMembers(depState.getMembers()); //TODO : make sure this still works after changing to list of MemberReps
                    newNeeds.addAll(depState.getNeeds());
                } else
                    throw new RuntimeException("Something went wrong with dependencies.");
            } else {
                throw new RuntimeException("Required Dependency " + path + " not found.");
            }
        }
        s.setNeeds(newNeeds); //replace old needs with the new needs
        if (s.hasNeeds())
            dependants.add(s);
    }

    return plaidpath;
}

From source file:org.opendaylight.vpnservice.elan.internal.ElanInterfaceManager.java

void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
    Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
    if (elanInterfaces == null || elanInterfaces.isEmpty()) {
        return;/*  w w w .j a va  2  s.  co m*/
    }
    for (ElanInterface elanInterface : elanInterfaces) {
        String interfaceName = elanInterface.getName();
        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
        addElanInterface(elanInterface, interfaceInfo, elanInstance);
    }
}

From source file:org.dkpro.lab.engine.impl.MultiThreadBatchTaskEngine.java

@Override
protected void executeConfiguration(BatchTask aConfiguration, TaskContext aContext, Map<String, Object> aConfig,
        Set<String> aExecutedSubtasks) throws ExecutionException, LifeCycleException {
    if (log.isTraceEnabled()) {
        // Show all subtasks executed so far
        for (String est : aExecutedSubtasks) {
            log.trace("-- Already executed: " + est);
        }//from w ww  . j  ava 2  s. c o  m
    }

    // Set up initial scope used by sub-batch-tasks using the inherited scope. The scope is
    // extended as the subtasks of this batch are executed with the present configuration.
    // FIXME: That means that sub-batch-tasks in two different configurations cannot see
    // each other. Is that intended? Mind that the "executedSubtasks" set is intentionally
    // maintained *across* configurations, so maybe the scope should also be maintained
    // *across* configurations? - REC 2014-06-15
    Set<String> scope = new HashSet<>();
    if (aConfiguration.getScope() != null) {
        scope.addAll(aConfiguration.getScope());
    }

    // Configure subtasks
    for (Task task : aConfiguration.getTasks()) {
        // Now the setup is complete
        aContext.getLifeCycleManager().configure(aContext, task, aConfig);
    }

    Queue<Task> queue = new LinkedList<>(aConfiguration.getTasks());
    // keeps track of the execution threads; 
    // TODO MW: do we really need this or can we work with the futures list only?
    Map<Task, ExecutionThread> threads = new HashMap<>();
    // keeps track of submitted Futures and their associated tasks
    Map<Future<?>, Task> futures = new HashMap<Future<?>, Task>();
    // will be instantiated with all exceptions from current loop
    ConcurrentMap<Task, Throwable> exceptionsFromLastLoop = null;
    ConcurrentMap<Task, Throwable> exceptionsFromCurrentLoop = new ConcurrentHashMap<>();

    int outerLoopCounter = 0;

    // main loop
    do {
        outerLoopCounter++;

        threads.clear();
        futures.clear();
        ExecutorService executor = Executors.newFixedThreadPool(maxThreads);

        // set the exceptions from the last loop
        exceptionsFromLastLoop = new ConcurrentHashMap<>(exceptionsFromCurrentLoop);

        // Fix MW: Clear exceptionsFromCurrentLoop; otherwise the loop with run at most twice.
        exceptionsFromCurrentLoop.clear();

        // process all tasks from the queue
        while (!queue.isEmpty()) {
            Task task = queue.poll();

            TaskContextMetadata execution = getExistingExecution(aConfiguration, aContext, task, aConfig,
                    aExecutedSubtasks);

            // Check if a subtask execution compatible with the present configuration has
            // does already exist ...
            if (execution == null) {
                // ... otherwise execute it with the present configuration
                log.info("Executing task [" + task.getType() + "]");

                // set scope here so that the inherited scopes are considered
                if (task instanceof BatchTask) {
                    ((BatchTask) task).setScope(scope);
                }

                ExecutionThread thread = new ExecutionThread(aContext, task, aConfig, aExecutedSubtasks);
                threads.put(task, thread);

                futures.put(executor.submit(thread), task);
            } else {
                log.debug("Using existing execution [" + execution.getId() + "]");

                // Record new/existing execution
                aExecutedSubtasks.add(execution.getId());
                scope.add(execution.getId());
            }
        }

        // try and get results from all futures to check for failed executions
        for (Map.Entry<Future<?>, Task> entry : futures.entrySet()) {
            try {
                entry.getKey().get();
            } catch (java.util.concurrent.ExecutionException ex) {
                Task task = entry.getValue();
                // TODO MW: add a retry-counter here to prevent endless loops?
                log.info("Task exec failed for [" + task.getType() + "]");
                // record the failed task, so that it can be re-added to the queue
                exceptionsFromCurrentLoop.put(task, ex);
            } catch (InterruptedException ex) {
                // thread interrupted, exit
                throw new RuntimeException(ex);
            }
        }

        log.debug("Calling shutdown");
        executor.shutdown();
        log.debug("All threads finished");

        // collect the results
        for (Map.Entry<Task, ExecutionThread> entry : threads.entrySet()) {
            Task task = entry.getKey();
            ExecutionThread thread = entry.getValue();
            TaskContextMetadata execution = thread.getTaskContextMetadata();

            // probably failed
            if (execution == null) {
                Throwable exception = exceptionsFromCurrentLoop.get(task);
                if (!(exception instanceof UnresolvedImportException)
                        && !(exception instanceof java.util.concurrent.ExecutionException)) {
                    throw new RuntimeException(exception);
                }
                exceptionsFromCurrentLoop.put(task, exception);

                // re-add to the queue
                queue.add(task);
            } else {

                // Record new/existing execution
                aExecutedSubtasks.add(execution.getId());
                scope.add(execution.getId());
            }
        }

    }
    // finish if the same tasks failed again
    while (!exceptionsFromCurrentLoop.keySet().equals(exceptionsFromLastLoop.keySet()));
    // END OF DO; finish if the same tasks failed again

    if (!exceptionsFromCurrentLoop.isEmpty()) {
        // collect all details
        StringBuilder details = new StringBuilder();
        for (Throwable throwable : exceptionsFromCurrentLoop.values()) {
            details.append("\n -");
            details.append(throwable.getMessage());
        }

        // we re-throw the first exception
        Throwable next = exceptionsFromCurrentLoop.values().iterator().next();
        if (next instanceof RuntimeException) {
            throw (RuntimeException) next;
        }

        // otherwise wrap it
        throw new RuntimeException(details.toString(), next);
    }
    log.info("MultiThreadBatchTask completed successfully. Total number of outer loop runs: "
            + outerLoopCounter);
}