package net.ion.craken.node.crud; import java.sql.SQLException; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import net.ion.craken.expression.ExpressionParser; import net.ion.craken.expression.SelectProjection; import net.ion.craken.expression.TerminalParser; import net.ion.craken.node.AbstractChildren; import net.ion.craken.node.IteratorList; import net.ion.craken.node.ReadNode; import net.ion.craken.node.ReadSession; import net.ion.craken.node.SortElement; import net.ion.craken.node.convert.rows.AdNodeRows; import net.ion.craken.node.convert.rows.FieldContext; import net.ion.craken.node.convert.rows.FieldDefinition; 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.ReadChildrenEachs; import net.ion.framework.db.Page; import net.ion.framework.db.Rows; import net.ion.framework.util.Debug; import net.ion.framework.util.ListUtil; import net.ion.framework.util.StringUtil; import net.ion.rosetta.Parser; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterators; public class ReadChildren extends AbstractChildren<ReadNode, ReadChildren> implements Iterable<ReadNode>{ private int skip = 0; private int offset = 10000; private List<SortElement> sorts ; private List<Predicate<ReadNode>> filters ; private final ReadSession session; private Fqn sourceFqn; // parent or refsource private Iterator<Fqn> treeFqns ; ReadChildren(ReadSession session, Fqn sourceFqn, Iterator<Fqn> treeFqns) { this.session = session; this.sourceFqn = sourceFqn ; this.treeFqns = treeFqns ; this.sorts = ListUtil.newList(); this.filters = ListUtil.newList(); } public ReadChildren skip(int skip) { this.skip = skip; return this; } public ReadChildren offset(int offset) { this.offset = offset; return this; } protected Fqn sourceFqn(){ return sourceFqn ; } public Iterator<Fqn> treeFqn(){ return treeFqns ; } protected TreeNode<PropertyId, PropertyValue> source(){ return session.workspace().readNode(sourceFqn) ; } protected ReadSession session(){ return session ; } protected int skip(){ return skip ; } protected int offset(){ return offset ; } protected List<SortElement> sorts(){ return sorts ; } protected List<Predicate<ReadNode>> filters(){ return filters ; } public <T> T eachNode(ReadChildrenEach<T> reach){ List<ReadNode> targets = readChildren(); ReadChildrenIterator citer = ReadChildrenIterator.create(session, targets); T result = reach.handle(citer) ; return result ; } protected List<ReadNode> readChildren() { List<ReadNode> listNode = ListUtil.newList() ; Predicate<ReadNode> andFilters = Predicates.and(filters) ; while(treeFqns.hasNext()){ Fqn nextFqn = treeFqns.next() ; ReadNode read = ReadNodeImpl.load(session, nextFqn); if (andFilters.apply(read)) listNode.add(read) ; // apply filter } if (sorts.size() > 0) { Comparator<ReadNode> mycomparator = new Comparator<ReadNode>() { @Override public int compare(ReadNode left, ReadNode right) { for (SortElement sele : sorts) { PropertyValue leftProperty = left.property(sele.propid()); PropertyValue rightProperty = right.property(sele.propid()); if (leftProperty == PropertyValue.NotFound && rightProperty == PropertyValue.NotFound) return 0; if (leftProperty == PropertyValue.NotFound) return -1 * (sele.ascending() ? 1 : -1); if (rightProperty == PropertyValue.NotFound) return 1 * (sele.ascending() ? 1 : -1); int result = leftProperty.compareTo(rightProperty) * (sele.ascending() ? 1 : -1); if (result != 0) return result ; } return 0; } }; Collections.sort(listNode, mycomparator); // apply sort } if (listNode.size() < skip) return ListUtil.EMPTY ; List<ReadNode> result = listNode.subList(skip, Math.min(skip + offset, listNode.size())) ; // apply skip & offset return result ; } public ReadChildren ascending(String propId) { sorts.add(new SortElement(propId, true)); return this; } public ReadChildren descending(String propId) { sorts.add(new SortElement(propId, false)); return this; } public ReadChildren filter(Predicate<ReadNode> filter) { filters.add(filter); return this; } @Deprecated public Rows toRows(String... cols) throws SQLException { return toAdRows(StringUtil.join(cols, ',')) ; } @Deprecated public Rows toRows(Page _page, String... cols) throws SQLException { return toAdRows(_page, StringUtil.join(cols, ',')) ; } public Rows toAdRows(String expr) { return AdNodeRows.create(session, iterator(), expr); } public Rows toAdRows(String expr, FieldDefinition... fieldDefinitons) { return AdNodeRows.create(session, iterator(), expr, fieldDefinitons); } public Rows toAdRows(Page _page, String expr, FieldDefinition... fieldDefinitons) { Page page = (_page == Page.ALL) ? Page.create(10000, 1) : _page; // limit Iterator<ReadNode> iter = readChildren().iterator() ; Iterators.skip(iter, page.getSkipOnScreen()) ; Iterator<ReadNode> limitIter = Iterators.limit(iter, page.getOffsetOnScreen()); List<ReadNode> screenList = ListUtil.newList() ; while(limitIter.hasNext()){ screenList.add(limitIter.next()) ; } int count = screenList.size(); Page pageOnScreen = Page.create(page.getListNum(), page.getPageNo() % page.getScreenCount() == 0 ? page.getScreenCount() : page.getPageNo() % page.getScreenCount(), page.getScreenCount()) ; return AdNodeRows.create(session, pageOnScreen.subList(screenList).iterator(), expr, fieldDefinitons, count, "cnt"); } public ReadNode firstNode() { return eachNode(ReadChildrenEachs.FIRSTNODE); } public List<ReadNode> toList() { return eachNode(ReadChildrenEachs.LIST); } public IteratorList<ReadNode> iterator(){ return eachNode(ReadChildrenEachs.ITERATOR) ; } public void debugPrint() { eachNode(ReadChildrenEachs.DEBUG); } public int count() { return eachNode(ReadChildrenEachs.COUNT); } public WalkReadChildren asTreeChildren() { return (WalkReadChildren)this; } public PropertyValue min(final String propId) { return eachNode(new ReadChildrenEach<PropertyValue>(){ @Override public PropertyValue handle(ReadChildrenIterator citer) { List<PropertyValue> store = ListUtil.newList() ; while(citer.hasNext()){ ReadNode rnode = citer.next() ; store.add(rnode.property(propId)) ; } Collections.sort(store); return store.size() > 0 ? store.get(0) : PropertyValue.NotFound; } }) ; } public PropertyValue max(final String propId) { return eachNode(new ReadChildrenEach<PropertyValue>(){ @Override public PropertyValue handle(ReadChildrenIterator citer) { List<PropertyValue> store = ListUtil.newList() ; while(citer.hasNext()){ ReadNode rnode = citer.next() ; store.add(rnode.property(propId)) ; } Collections.sort(store); Collections.reverse(store); return store.size() > 0 ? store.get(0) : PropertyValue.NotFound; } }) ; } }