/** * Does a 'breadth first' search of ancestors, caching as it goes * * @param nodeIds initial list of nodes to visit * @return all visited nodes, in no particular order */ private List<Long> cacheAncestors(List<Long> nodeIds) { final LinkedList<Long> toVisit = new LinkedList<Long>(nodeIds); Set<Long> visited = new TreeSet<Long>(); Long nodeId; nodeDAO.cacheNodesById(toVisit); Long lastCached = toVisit.peekLast(); while ((nodeId = toVisit.pollFirst()) != null) { if (visited.add(nodeId) && (nodeDAO.getNodeIdStatus(nodeId) != null) && (false == nodeDAO.getNodeIdStatus(nodeId).isDeleted())) { nodeDAO.getParentAssocs( nodeId, null, null, null, new ChildAssocRefQueryCallback() { @Override public boolean preLoadNodes() { return false; } @Override public boolean orderResults() { return false; } @Override public boolean handle( Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) { toVisit.add(parentNodePair.getFirst()); return true; } @Override public void done() {} }); } final boolean nodeIdEqualsLastCached = (nodeId == null && lastCached == null) || (nodeId != null && nodeId.equals(lastCached)); if (nodeIdEqualsLastCached && !toVisit.isEmpty()) { nodeDAO.cacheNodesById(toVisit); lastCached = toVisit.peekLast(); } } return new ArrayList<Long>(visited); }
private List<Long> preCacheNodes(NodeMetaDataParameters nodeMetaDataParameters) { int maxResults = nodeMetaDataParameters.getMaxResults(); boolean isLimitSet = (maxResults != 0 && maxResults != Integer.MAX_VALUE); List<Long> nodeIds = null; Iterable<Long> iterable = null; List<Long> allNodeIds = nodeMetaDataParameters.getNodeIds(); if (allNodeIds != null) { int toIndex = (maxResults > allNodeIds.size() ? allNodeIds.size() : maxResults); nodeIds = isLimitSet ? allNodeIds.subList(0, toIndex) : nodeMetaDataParameters.getNodeIds(); iterable = nodeMetaDataParameters.getNodeIds(); } else { Long fromNodeId = nodeMetaDataParameters.getFromNodeId(); Long toNodeId = nodeMetaDataParameters.getToNodeId(); nodeIds = new ArrayList<Long>(isLimitSet ? maxResults : 100); // TODO better default here? iterable = new SequenceIterator(fromNodeId, toNodeId, maxResults); int counter = 1; for (Long nodeId : iterable) { if (isLimitSet && counter++ > maxResults) { break; } nodeIds.add(nodeId); } } // Pre-evaluate ancestors so we can bulk load them List<Long> ancestors; if (cacheAncestors) { ancestors = cacheAncestors(nodeIds); } else { ancestors = nodeIds; } // Ensure that we get fresh node references nodeDAO.setCheckNodeConsistency(); // bulk load nodes and their ancestors nodeDAO.cacheNodesById(ancestors); return nodeIds; }