Example usage for java.util Queue poll

List of usage examples for java.util Queue poll

Introduction

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

Prototype

E poll();

Source Link

Document

Retrieves and removes the head of this queue, or returns null if this queue is empty.

Usage

From source file:net.sf.eventgraphj.centrality.EgoNetworkBetweennessCentrality.java

protected void computeBetweenness(Queue<V> queue, Transformer<E, ? extends Number> edge_weights) {
    for (V v : graph.getVertices()) {
        // initialize the betweenness data for this new vertex
        for (V s : graph.getVertices())
            this.vertex_data.put(s, new BetweennessData());

        //         if (v.equals(new Integer(0)))
        //            System.out.println("pause");

        vertex_data.get(v).numSPs = 1;//  w w  w. j  a  v a 2 s.c o m
        vertex_data.get(v).distance = 0;

        Stack<V> stack = new Stack<V>();
        //            Buffer<V> queue = new UnboundedFifoBuffer<V>();
        //            queue.add(v);
        queue.offer(v);

        while (!queue.isEmpty()) {
            //                V w = queue.remove();
            V w = queue.poll();
            stack.push(w);
            BetweennessData w_data = vertex_data.get(w);
            for (E e : graph.getOutEdges(w)) {
                // TODO (jrtom): change this to getOtherVertices(w, e)
                V x = graph.getOpposite(w, e);
                if (x.equals(w))
                    continue;
                double wx_weight = edge_weights.transform(e).doubleValue();

                //                for(V x : graph.getSuccessors(w)) 
                //                {
                //                   if (x.equals(w))
                //                      continue;

                // FIXME: the other problem is that I need to 
                // keep putting the neighbors of things we've just 
                // discovered in the queue, if they're undiscovered or
                // at greater distance.

                // FIXME: this is the problem, right here, I think: 
                // need to update position in queue if distance changes
                // (which can only happen with weighted edges).
                // for each outgoing edge e from w, get other end x
                // if x not already visited (dist x < 0)
                //   set x's distance to w's dist + edge weight
                //   add x to queue; pri in queue is x's dist
                // if w's dist + edge weight < x's dist 
                //   update x's dist
                //   update x in queue (MapBinaryHeap)
                //   clear x's incoming edge list
                // if w's dist + edge weight = x's dist
                //   add e to x's incoming edge list

                BetweennessData x_data = vertex_data.get(x);
                double x_potential_dist = w_data.distance + wx_weight;
                if (x_potential_dist > this.egoNetworkSize)
                    continue;

                if (x_data.distance < 0) {
                    //                        queue.add(x);
                    //                        vertex_data.get(x).distance = vertex_data.get(w).distance + 1;
                    x_data.distance = x_potential_dist;
                    queue.offer(x);
                }

                // note:
                // (1) this can only happen with weighted edges
                // (2) x's SP count and incoming edges are updated below 
                if (x_data.distance > x_potential_dist) {
                    x_data.distance = x_potential_dist;
                    // invalidate previously identified incoming edges
                    // (we have a new shortest path distance to x)
                    x_data.incomingEdges.clear();
                    // update x's position in queue
                    ((MapBinaryHeap<V>) queue).update(x);
                }
                //                  if (vertex_data.get(x).distance == vertex_data.get(w).distance + 1) 
                // 
                //                    if (x_data.distance == x_potential_dist) 
                //                    {
                //                        x_data.numSPs += w_data.numSPs;
                ////                        vertex_data.get(x).predecessors.add(w);
                //                        x_data.incomingEdges.add(e);
                //                    }
            }
            for (E e : graph.getOutEdges(w)) {
                V x = graph.getOpposite(w, e);
                if (x.equals(w))
                    continue;
                double e_weight = edge_weights.transform(e).doubleValue();
                BetweennessData x_data = vertex_data.get(x);
                double x_potential_dist = w_data.distance + e_weight;
                if (x_data.distance == x_potential_dist) {
                    x_data.numSPs += w_data.numSPs;
                    //                        vertex_data.get(x).predecessors.add(w);
                    x_data.incomingEdges.add(e);
                }
            }
        }
        while (!stack.isEmpty()) {
            V x = stack.pop();

            //              for (V w : vertex_data.get(x).predecessors) 
            for (E e : vertex_data.get(x).incomingEdges) {
                V w = graph.getOpposite(x, e);
                double partialDependency = vertex_data.get(w).numSPs / vertex_data.get(x).numSPs
                        * (1.0 + vertex_data.get(x).dependency);
                vertex_data.get(w).dependency += partialDependency;
                //                  E w_x = graph.findEdge(w, x);
                //                  double w_x_score = edge_scores.get(w_x).doubleValue();
                //                  w_x_score += partialDependency;
                //                  edge_scores.put(w_x, w_x_score);
                double e_score = edge_scores.get(e).doubleValue();
                edge_scores.put(e, e_score + partialDependency);
            }
            if (!x.equals(v)) {
                double x_score = vertex_scores.get(x).doubleValue();
                x_score += vertex_data.get(x).dependency;
                vertex_scores.put(x, x_score);
            }
        }
    }

    if (graph instanceof UndirectedGraph) {
        for (V v : graph.getVertices()) {
            double v_score = vertex_scores.get(v).doubleValue();
            v_score /= 2.0;
            vertex_scores.put(v, v_score);
        }
        for (E e : graph.getEdges()) {
            double e_score = edge_scores.get(e).doubleValue();
            e_score /= 2.0;
            edge_scores.put(e, e_score);
        }
    }

    vertex_data.clear();
}

From source file:org.apache.camel.component.file.GenericFileConsumer.java

@SuppressWarnings("unchecked")
public int processBatch(Queue<Object> exchanges) {
    int total = exchanges.size();

    // limit if needed
    if (maxMessagesPerPoll > 0 && total > maxMessagesPerPoll) {
        if (log.isDebugEnabled()) {
            log.debug("Limiting to maximum messages to poll " + maxMessagesPerPoll + " as there was " + total
                    + " messages in this poll.");
        }//from  w w w .  j a  v  a2  s .  com
        total = maxMessagesPerPoll;
    }

    for (int index = 0; index < total && isBatchAllowed(); index++) {
        // only loop if we are started (allowed to run)
        // use poll to remove the head so it does not consume memory even after we have processed it
        Exchange exchange = (Exchange) exchanges.poll();
        // add current index and total as properties
        exchange.setProperty(Exchange.BATCH_INDEX, index);
        exchange.setProperty(Exchange.BATCH_SIZE, total);
        exchange.setProperty(Exchange.BATCH_COMPLETE, index == total - 1);

        // update pending number of exchanges
        pendingExchanges = total - index - 1;

        // process the current exchange
        processExchange(exchange);
    }

    // remove the file from the in progress list in case the batch was limited by max messages per poll
    while (exchanges.size() > 0) {
        Exchange exchange = (Exchange) exchanges.poll();
        GenericFile<T> file = (GenericFile<T>) exchange.getProperty(FileComponent.FILE_EXCHANGE_FILE);
        String key = file.getAbsoluteFilePath();
        endpoint.getInProgressRepository().remove(key);
    }

    return total;
}

From source file:org.eclipse.tracecompass.statesystem.core.tests.perf.historytree.HistoryTreeBackendBenchmark.java

/**
 * Benchmarks creating, single querying and full querying the state system
 *//*from   w ww .  j a va2 s  . c o m*/
@Test
public void testBenchmark() {
    /* Check arguments */
    long totalTime = this.fNbAvgIntervals * INTERVAL_AVG_TIME;

    Performance perf = Performance.getDefault();
    PerformanceMeter pmBuild = perf.createPerformanceMeter(TEST_PREFIX + TEST_BUILDING_ID + fName);
    perf.tagAsSummary(pmBuild, TEST_BUILDING_ID + fShortName, Dimension.CPU_TIME);

    PerformanceMeter pmSingleQuery = perf.createPerformanceMeter(TEST_PREFIX + TEST_SINGLE_QUERY_ID + fName);
    perf.tagAsSummary(pmSingleQuery, TEST_SINGLE_QUERY_ID + fShortName, Dimension.CPU_TIME);

    PerformanceMeter pmFullQuery = perf.createPerformanceMeter(TEST_PREFIX + TEST_FULL_QUERY_ID + fName);
    perf.tagAsSummary(pmFullQuery, TEST_FULL_QUERY_ID + fShortName, Dimension.CPU_TIME);

    PerformanceMeter pmRangeQuery = perf.createPerformanceMeter(TEST_PREFIX + TEST_QUERY_RANGE_ID + fName);
    perf.tagAsSummary(pmRangeQuery, TEST_QUERY_RANGE_ID + fShortName, Dimension.CPU_TIME);

    for (int i = 0; i < fNbLoops; i++) {
        try {
            /* Create the state system */
            createFile();
            IStateHistoryBackend backend = StateHistoryBackendFactory.createHistoryTreeBackendNewFile(
                    TEST_BUILDING_ID, NonNullUtils.checkNotNull(fTempFile), 1, 1, QUEUE_SIZE);
            ITmfStateSystemBuilder ss = StateSystemFactory.newStateSystem(backend);

            /* Initialize the attributes */
            Queue<QuarkEvent> quarkEvents = new PriorityQueue<>(fNbAttrib);
            Random randomGenerator = new Random(SEED);
            int rootQuark = ss.getQuarkAbsoluteAndAdd(ROOT_NODE);

            /* Create all attributes before testing */
            for (int j = 0; j < fNbAttrib; j++) {
                int quark = ss.getQuarkRelativeAndAdd(rootQuark, String.valueOf(j));
                quarkEvents.add(new QuarkEvent(quark,
                        (Math.abs(randomGenerator.nextLong()) % INTERVAL_AVG_TIME) + 1, fValues.getValues()));
            }

            /* Adds random intervals to the state system */
            pmBuild.start();
            while (true) {
                QuarkEvent quarkEvent = quarkEvents.poll();
                if (quarkEvent == null) {
                    break;
                }
                long eventTime = quarkEvent.getNextEventTime();
                ss.modifyAttribute(eventTime, quarkEvent.getNextValue(), quarkEvent.getQuark());
                long nextDelta = fDistributionMethod.getNextEndTime(randomGenerator, INTERVAL_AVG_TIME);
                long nextEndTime = eventTime + nextDelta;
                if (nextEndTime <= totalTime) {
                    quarkEvent.setNextEventTime(nextEndTime);
                    quarkEvents.add(quarkEvent);
                }
            }
            ss.closeHistory(totalTime);
            pmBuild.stop();

            /*
             * Benchmark the single queries: for each random timestamp,
             * query a random attribute
             */
            List<Integer> subAttributes = ss.getSubAttributes(rootQuark, false);
            pmSingleQuery.start();
            for (int j = 0; j < QUERY_COUNT; j++) {
                long ts = getNextRandomValue(randomGenerator, totalTime);
                int attrib = (int) getNextRandomValue(randomGenerator, subAttributes.size());
                ss.querySingleState(ts, attrib);
            }
            pmSingleQuery.stop();

            /* Benchmark the history range query of 10 attributes */
            pmRangeQuery.start();
            for (int j = 0; j < 10; j++) {
                int attrib = (int) getNextRandomValue(randomGenerator, subAttributes.size());
                StateSystemUtils.queryHistoryRange(ss, attrib, ss.getStartTime(), ss.getCurrentEndTime());
            }
            pmRangeQuery.stop();

            /* Benchmark the full queries */
            pmFullQuery.start();
            for (int j = 0; j < QUERY_COUNT; j++) {
                long ts = getNextRandomValue(randomGenerator, totalTime);
                ss.queryFullState(ts);
            }
            pmFullQuery.stop();

            /* Output some data on the file */
            if (i == 0) {
                if (backend instanceof HistoryTreeBackend) {
                    HistoryTreeBackend htBackend = (HistoryTreeBackend) backend;
                    System.out.println("History tree file size: "
                            + FileUtils.byteCountToDisplaySize(htBackend.getFileSize()));
                    System.out.println("Average node usage: " + htBackend.getAverageNodeUsage());
                }
            }
            deleteFile();
        } catch (IOException | StateValueTypeException | AttributeNotFoundException
                | StateSystemDisposedException e) {
            fail(e.getMessage());
        } finally {
            deleteFile();
        }
    }
    pmBuild.commit();
    pmSingleQuery.commit();
    pmFullQuery.commit();
    pmRangeQuery.commit();
}

From source file:org.kuali.student.enrollment.class1.krms.service.impl.FERuleEditorMaintainableImpl.java

public AgendaItemDefinition maintainAgendaItems(AgendaEditor agenda, String namePrefix, String nameSpace) {

    Queue<RuleDefinition.Builder> rules = new LinkedList<RuleDefinition.Builder>();
    FEAgendaEditor feAgenda;/* w w w  .  ja  va  2  s  .c o  m*/
    if (agenda instanceof FEAgendaEditor) {
        feAgenda = (FEAgendaEditor) agenda;
        for (RuleEditor rule : feAgenda.getRules()) {
            if (!rule.isDummy()) {
                rules.add(this.finRule(rule, namePrefix, nameSpace));
            }
        }

        AgendaItemDefinition.Builder rootItemBuilder = manageFirstItem(agenda);

        AgendaItemDefinition.Builder itemToDelete = null;
        AgendaItemDefinition.Builder itemBuilder = rootItemBuilder;
        while (rules.peek() != null) {
            itemBuilder.setRule(rules.poll());
            itemBuilder.setRuleId(itemBuilder.getRule().getId());
            if (rules.peek() != null) {
                if (itemBuilder.getWhenFalse() == null) {
                    itemBuilder.setWhenFalse(AgendaItemDefinition.Builder.create(null, agenda.getId()));
                }
                itemBuilder = itemBuilder.getWhenFalse();
            } else {
                itemToDelete = itemBuilder.getWhenFalse();
                itemBuilder.setWhenFalse(null);
            }
        }

        return manageAgendaItems(agenda, rootItemBuilder, itemToDelete);
    }

    return null;
}

From source file:org.exoplatform.ecm.webui.component.explorer.rightclick.manager.DeleteManageComponent.java

private void processRemoveOrMoveToTrash(String nodePath, Node node, Event<?> event, boolean isMultiSelect,
        boolean checkToMoveToTrash) throws Exception {
    if (!checkToMoveToTrash || Utils.isInTrash(node))
        processRemoveNode(nodePath, node, event, isMultiSelect);
    else {/*  w ww .  j  av  a2  s  .  c  o m*/
        WCMComposer wcmComposer = WCMCoreUtils.getService(WCMComposer.class);
        List<Node> categories = WCMCoreUtils.getService(TaxonomyService.class).getAllCategories(node);

        String parentPath = node.getParent().getPath();
        String parentWSpace = node.getSession().getWorkspace().getName();

        wcmComposer.updateContent(parentWSpace, node.getPath(), new HashMap<String, String>());
        boolean isNodeReferenceable = Utils.isReferenceable(node);
        String nodeUUID = null;
        if (isNodeReferenceable)
            nodeUUID = node.getUUID();
        boolean moveOK = moveToTrash(nodePath, node, event, isMultiSelect);
        if (moveOK) {
            for (Node categoryNode : categories) {
                wcmComposer.updateContents(categoryNode.getSession().getWorkspace().getName(),
                        categoryNode.getPath(), new HashMap<String, String>());
            }
            PortletRequestContext pcontext = (PortletRequestContext) WebuiRequestContext.getCurrentInstance();

            PortletPreferences portletPref = pcontext.getRequest().getPreferences();

            String trashWorkspace = portletPref.getValue(Utils.TRASH_WORKSPACE, "");
            if (isNodeReferenceable) {
                wcmComposer.updateContent(trashWorkspace, nodeUUID, new HashMap<String, String>());
            }
            wcmComposer.updateContents(parentWSpace, parentPath, new HashMap<String, String>());
            //Broadcast the event when user move node to Trash
            ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class);
            ActivityCommonService activityService = WCMCoreUtils.getService(ActivityCommonService.class);
            Node parent = node.getParent();
            if (node.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
                if (activityService.isBroadcastNTFileEvents(node)) {
                    listenerService.broadcast(ActivityCommonService.FILE_REMOVE_ACTIVITY, parent, node);
                }
            } else if (!isDocumentNodeType(node)) {
                Queue<Node> queue = new LinkedList<Node>();
                queue.add(node);

                //Broadcast event to remove file activities
                Node tempNode = null;
                try {
                    while (!queue.isEmpty()) {
                        tempNode = queue.poll();
                        if (isDocumentNodeType(tempNode)
                                || tempNode.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
                            listenerService.broadcast(ActivityCommonService.FILE_REMOVE_ACTIVITY,
                                    tempNode.getParent(), tempNode);
                        } else {
                            for (NodeIterator iter = tempNode.getNodes(); iter.hasNext();) {
                                Node childNode = iter.nextNode();
                                if (isDocumentNodeType(childNode)
                                        || childNode.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)
                                        || childNode.isNodeType(NodetypeConstant.NT_FOLDER))
                                    queue.add(childNode);
                            }
                        }
                    }
                } catch (Exception e) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn(e.getMessage());
                    }
                }

            }
        }
    }
}

From source file:org.kuali.rice.krms.service.impl.RuleEditorMaintainableImpl.java

public AgendaItemDefinition maintainAgendaItems(AgendaEditor agenda, String namePrefix, String nameSpace) {

    Queue<RuleDefinition.Builder> rules = new LinkedList<RuleDefinition.Builder>();
    for (RuleEditor rule : agenda.getRuleEditors().values()) {
        if (!rule.isDummy()) {
            rules.add(this.finRule(rule, namePrefix, nameSpace));
        }/*from  w  ww . j a  va  2 s. com*/
    }

    AgendaItemDefinition.Builder rootItemBuilder = manageFirstItem(agenda);

    AgendaItemDefinition.Builder itemToDelete = null;
    AgendaItemDefinition.Builder itemBuilder = rootItemBuilder;
    while (rules.peek() != null) {
        itemBuilder.setRule(rules.poll());
        itemBuilder.setRuleId(itemBuilder.getRule().getId());
        if (rules.peek() != null) {
            if (itemBuilder.getWhenTrue() == null) {
                itemBuilder.setWhenTrue(AgendaItemDefinition.Builder.create(null, agenda.getId()));
            }
            itemBuilder = itemBuilder.getWhenTrue();
        } else {
            itemToDelete = itemBuilder.getWhenTrue();
            itemBuilder.setWhenTrue(null);
        }
    }

    return manageAgendaItems(agenda, rootItemBuilder, itemToDelete);
}

From source file:eu.netide.mms.MMSManager.java

private List<MMSStoreEntry> searchRuleGraph(MMSStoreEntry entry) {

    Queue<MMSStoreEntry> queue = new LinkedList<MMSStoreEntry>();
    List<MMSStoreEntry> listToDelete = Lists.newArrayList();
    MMSStoreEntry copyEntry = new DefaultMMSEntry(entry);

    copyEntry.setVisited(true);/*www  . j  a  v a2s .c  o  m*/
    queue.add(copyEntry);

    while (!queue.isEmpty()) {
        MMSStoreEntry v = queue.poll();
        for (MMSStoreEntry w : v.getRuleParents()) {
            MMSStoreEntry copyInside = new DefaultMMSEntry(w);
            if (!copyInside.getVisited()) {
                copyInside.setVisited(true);
                queue.add(copyInside);
                listToDelete.add(w);
            }
        }
    }

    return listToDelete;
}

From source file:org.jboss.errai.ioc.rebind.ioc.graph.impl.DependencyGraphBuilderImpl.java

private void removeUnreachableConcreteInjectables() {
    final Set<String> reachableNames = new HashSet<String>();
    final Queue<Injectable> processingQueue = new LinkedList<Injectable>();
    for (final Injectable injectable : concretesByName.values()) {
        if (!injectable.getWiringElementTypes().contains(WiringElementType.Simpleton)
                && !reachableNames.contains(injectable.getFactoryName())) {
            processingQueue.add(injectable);
            do {/*from   www.  j av a  2 s  .  co  m*/
                final Injectable processedInjectable = processingQueue.poll();
                reachableNames.add(processedInjectable.getFactoryName());
                for (final Dependency dep : processedInjectable.getDependencies()) {
                    final Injectable resolvedDep = getResolvedDependency(dep, processedInjectable);
                    if (!reachableNames.contains(resolvedDep.getFactoryName())) {
                        processingQueue.add(resolvedDep);
                    }
                }
            } while (processingQueue.size() > 0);
        }
    }

    concretesByName.keySet().retainAll(reachableNames);
}

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

/**
 * ??, ???, ??://www  . j  a v  a2s .  c  o  m
 * 1) , ?????
 * 2) ????, , ?
 *
 * @return true  , false ?
 */
public synchronized boolean isConnected() {
    Queue<VK> q = new LinkedList<>();
    Set<VK> hasVisited = new HashSet<>();

    // ?
    Iterator<Map.Entry<VK, VD>> iter = vertices.entrySet().iterator();

    // ,  true
    if (!iter.hasNext()) {
        return true;
    }

    // ????
    Map.Entry<VK, VD> entry = iter.next();

    VK startKey = entry.getKey();

    q.add(startKey);
    hasVisited.add(startKey);

    while (!q.isEmpty()) {
        VK key = q.poll();

        for (VK postKey : getPostNode(key)) {
            if (!hasVisited.contains(postKey)) {
                q.add(postKey);
                hasVisited.add(postKey);
            }
        }

        for (VK preKey : getPreNode(key)) {
            if (!hasVisited.contains(preKey)) {
                q.add(preKey);
                hasVisited.add(preKey);
            }
        }
    }

    return hasVisited.size() == getVertexNumber();
}

From source file:com.bluepowermod.part.tube.TubeLogic.java

/**
 * This method gets the end target and heading for a TubeStack. When the tubestack's target variable is null, this is an exporting item, meaning
 * the returned target will be the TileEntity the item is going to transport to. When the tubestack's target variable is not not, the item is
 * being retrieved to this inventory. The returned target is the inventory the item came/should come from.
 *
 * @param simulate/*from www.j a  v  a 2s. c  o  m*/
 *            The only difference between simulate and not simulate is the fact that the round robin handling will be updated in non-simulate.
 * @param from
 *            The direction this item came from, this direction will never be a valid heading. Is null in normal item routing, as the from
 *            direction IS a valid output.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
private Pair<ForgeDirection, TileEntity> getHeadingForItem(TubeStack stack, boolean simulate) {

    Map<TubeNode, Integer> distances = new HashMap<TubeNode, Integer>();
    Queue<TubeNode> traversingNodes = new LinkedBlockingQueue<TubeNode>();
    Queue<ForgeDirection> trackingExportDirection = new LinkedBlockingQueue<ForgeDirection>();
    Map<TubeEdge, ForgeDirection> validDestinations = new LinkedHashMap<TubeEdge, ForgeDirection>();// using a LinkedHashMap so the order doesn't
    // change, used for round robin.

    if (getNode() != null) {
        distances.put(getNode(), 0);// make this the origin.
        traversingNodes.add(getNode());
    }

    boolean firstRun = true;
    int closestDest = 0;
    while (!traversingNodes.isEmpty()) {
        TubeNode node = traversingNodes.poll();
        if (node.edges == null)
            node.init();
        ForgeDirection heading = firstRun ? null : trackingExportDirection.poll();
        for (int i = 0; i < 6; i++) {
            if (firstRun)
                heading = ForgeDirection.getOrientation(i);
            if (node.edges != null) {
                TubeEdge edge = node.edges[i];
                if (edge != null && canPassThroughMask(stack.color, edge.colorMask)) {// if this item can travel through this color mask proceed.
                    Integer distance = distances.get(edge.target);
                    if (distance == null || distances.get(node) + edge.distance < distance) {
                        distances.put(edge.target, distances.get(node) + edge.distance);
                        if (edge.target.target instanceof PneumaticTube) {
                            traversingNodes.add(edge.target);
                            trackingExportDirection.add(heading);
                        } else if (stack.getTarget(tube.getWorld()) == null
                                && edge.isValidForExportItem(stack.stack)
                                || stack.heading == null && edge.isValidForImportItem(stack)
                                || stack.heading != null
                                        && stack.getTarget(tube.getWorld()) == edge.target.target
                                        && edge.targetConnectionSide.getOpposite() == stack
                                                .getTargetEntryDir()) {
                            validDestinations.put(edge,
                                    stack.heading == null ? edge.targetConnectionSide : heading);
                        }
                    }
                }
            }
        }

        // Check the distances of the current breadth first search layer. if no points are closer than the currently valid destination(s), we're
        // done searching.
        boolean isDoneSearching = true;
        closestDest = getClosestDestination(validDestinations.keySet(), distances);
        for (TubeNode checkingNode : traversingNodes) {
            if (distances.get(checkingNode) <= closestDest) {
                isDoneSearching = false;
                break;
            }
        }
        if (isDoneSearching)
            break;
        firstRun = false;
    }

    if (validDestinations.size() == 0) {
        if (stack.getTarget(tube.getWorld()) != null && stack.heading != null && !simulate) {
            stack.setTarget(null, ForgeDirection.UNKNOWN);// if we can't reach the retrieving target anymore, reroute as normal.
            return getHeadingForItem(stack, simulate);
        } else {
            return null;
        }
    }

    List<Pair<ForgeDirection, TileEntity>> validDirections = new ArrayList<Pair<ForgeDirection, TileEntity>>();
    for (Map.Entry<TubeEdge, ForgeDirection> entry : validDestinations.entrySet()) {
        if (distances.get(entry.getKey().target) == closestDest) {
            validDirections.add(new ImmutablePair(entry.getValue(), entry.getKey().target.target));
        }
    }

    // handle round robin
    if (!simulate)
        roundRobinCounter++;
    if (roundRobinCounter >= validDirections.size())
        roundRobinCounter = 0;
    return validDirections.get(roundRobinCounter);
}