/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.internal.query; import java.util.NoSuchElementException; /** * QueryIterator class. It iterates over the terms of a query tree. Useful for evaluating * candidate objects with a query. * * @author Tilmann Zaeschke */ public final class QueryTreeIterator { private QueryTreeNode currentNode; //private boolean askFirst = true; private final boolean[] askFirstA = new boolean[20]; //0==first; 1==2nd; 2==done private int askFirstD = 0; //depth: 0=root private QueryTerm nextElement = null; QueryTreeIterator(QueryTreeNode node) { currentNode = node; for (int i = 0; i < askFirstA.length; i++) { askFirstA[i] = true; } nextElement = findNext(); } public boolean hasNext() { return (nextElement != null); } /** * To avoid duplicate work in next() and hasNext() (both can locate the next element), * we automatically move to the next element when the previous is returned. The hasNext() * method then becomes trivial. * @return next element. */ public QueryTerm next() { if (nextElement == null) { throw new NoSuchElementException(); } QueryTerm t = nextElement; nextElement = findNext(); return t; } /** * Also, ASK nur setzen wenn ich hoch komme? * runter: true-> first; false second; * hoch: true-> nextSecond; false-> nextUP */ private QueryTerm findNext() { //Walk down first branch if (askFirstA[askFirstD]) { while (currentNode.firstTerm() == null) { //remember that we already walked down the first branch askFirstD++; currentNode = currentNode.firstNode(); } askFirstA[askFirstD] = false; return currentNode.firstTerm(); } //do we have a second branch? if (currentNode.isUnary()) { return findUpwards(); } //walk down second branch if (currentNode.secondTerm() != null) { //dirty hack if (currentNode.secondTerm() != nextElement) { return currentNode.secondTerm(); } //else: we have been here before! //walk back up return findUpwards(); } else { currentNode = currentNode.secondNode(); askFirstD++; return findNext(); } } private QueryTerm findUpwards() { if (currentNode.p == null) { return null; } do { //clean up behind me before moving back up askFirstA[askFirstD] = true; askFirstD--; currentNode = currentNode.parent(); } while (currentNode.p != null && (currentNode.isUnary() || !askFirstA[askFirstD])); //remove, only for DEBUG // if (_currentNode == null) { // throw new NoSuchElementException(); // } //if 'false' then we are finished if (!askFirstA[askFirstD]) { return null; } //indicate that we want the second branch now askFirstA[askFirstD] = false; //walk down second branch return findNext(); } }