package net.ion.craken.node.crud; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import net.ion.craken.node.ReadNode; import net.ion.craken.node.ReadSession; import net.ion.craken.node.SortElement; import net.ion.craken.node.crud.tree.Fqn; import net.ion.craken.node.crud.tree.TreeNode; import net.ion.craken.node.crud.tree.impl.PropertyId; import net.ion.craken.node.crud.tree.impl.PropertyValue; import net.ion.craken.node.crud.util.TraversalStrategy; import net.ion.framework.util.ListUtil; import net.ion.framework.util.SetUtil; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Lists; public class WalkReadChildren extends ReadChildren{ private TraversalStrategy strategy = TraversalStrategy.BreadthFirst ; private boolean includeSelf = false; private Predicate<ReadNode> andFilters; WalkReadChildren(ReadSession session, Fqn source, Iterator<Fqn> children) { super(session, source, children) ; } protected List<ReadNode> readChildren() { LinkedList<ReadNode> result = new LinkedList<ReadNode>(); WalkReadNode rootFrom = WalkReadNode.create(session(), null, sourceFqn(), 0); if (includeSelf) { result.add(rootFrom) ; } this.andFilters = Predicates.and(filters()) ; if (strategy == TraversalStrategy.BreadthFirst) this.buildBreadthList(result, makeWalk(rootFrom, treeFqn(), 1), 1); else this.buildDepthList(result, makeWalk(rootFrom, treeFqn(), 1), 1) ; return result.subList(skip(), Math.min(skip() + offset(), result.size())) ; } private List<WalkReadNode> readTreeChildren(){ List<WalkReadNode> result = ListUtil.newList() ; for(ReadNode rnode : readChildren()){ result.add((WalkReadNode)rnode) ; } return result ; } private Iterator<WalkReadNode> makeWalk(WalkReadNode rootFrom, Iterator<Fqn> treeNodes, int level) { Set<WalkReadNode> result = SetUtil.newSet() ; while(treeNodes.hasNext()){ result.add(WalkReadNode.create(session(), rootFrom, treeNodes.next(), level)) ; } return result.iterator(); } public <T> T eachTreeNode(WalkChildrenEach<T> trcEach) { WalkChildrenIterator trcIterable = WalkChildrenIterator.create(session(), readTreeChildren()) ; return trcEach.handle(trcIterable) ; } private List<TreeNode> buildBreadthList(LinkedList<ReadNode> list, Iterator<WalkReadNode> children, int level) { if (!children.hasNext()) return ListUtil.EMPTY ; Iterator<WalkReadNode> sortedChildren = sort(children) ; List<WalkReadNode> inner = ListUtil.newList() ; while(sortedChildren.hasNext()){ WalkReadNode child = sortedChildren.next(); WalkReadNode target = WalkReadNode.create(session(), child.from(), child.fqn(), level); if (! andFilters.apply(target)) continue ; list.add(target) ; inner.addAll(child.getChildren()) ; } return buildBreadthList(list, inner.iterator(), ++level) ; } private void buildDepthList(LinkedList<ReadNode> list, Iterator<WalkReadNode> children, int level) { Iterator<WalkReadNode> sortedChildren = sort(children) ; while(sortedChildren.hasNext()){ WalkReadNode child = sortedChildren.next(); WalkReadNode target = WalkReadNode.create(session(), child.from(), child.fqn(), level); if (andFilters.apply(target)) list.add(target) ; this.buildDepthList(list, child.getChildren().iterator(), (level+1)) ; } } private Iterator<WalkReadNode> sort(Iterator<WalkReadNode> children) { if (sorts().size() > 0) { List<WalkReadNode> childrenList = Lists.newArrayList(children) ; Comparator<WalkReadNode> mycomparator = new Comparator<WalkReadNode>() { @Override public int compare(WalkReadNode left, WalkReadNode right) { for (SortElement sele : sorts()) { PropertyId spid = PropertyId.fromIdString(sele.propid()) ; PropertyValue leftProperty = left.get(spid); PropertyValue rightProperty = right.get(spid); if (leftProperty == null && rightProperty == null) return 0; if (leftProperty == null) return -1 * (sele.ascending() ? 1 : -1); if (rightProperty == null) return 1 * (sele.ascending() ? 1 : -1); int result = leftProperty.compareTo(rightProperty) * (sele.ascending() ? 1 : -1); if (result != 0) return result ; } return 0; } }; Collections.sort(childrenList, mycomparator); // apply sort return childrenList.iterator() ; } return children; } public WalkReadChildren strategy(TraversalStrategy strategy) { this.strategy = strategy ; return this; } public WalkReadChildren includeSelf(boolean includeSelf){ this.includeSelf = includeSelf ; return this ; } }