package com.tesora.dve.sql.node;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.Stack;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
public abstract class AbstractTraversal<NT> {
public enum Order {
PREORDER,
POSTORDER,
NATURAL_ORDER // left to right order in the original sql
}
public enum ExecStyle {
ONCE,
REPEAT
}
protected final Order order;
protected final ExecStyle repeat;
protected final Stack<NT> path;
public AbstractTraversal(Order direction, ExecStyle execStyle) {
this.order = direction;
if (this.order == null)
throw new SchemaException(Pass.PLANNER, "Must specify ordering for traversal");
this.repeat = execStyle;
if (this.repeat == null)
throw new SchemaException(Pass.PLANNER, "Must specify execution style for traversal");
this.path = new Stack<NT>();
}
protected final Stack<NT> getPath() {
return path;
}
protected void push(NT ln) {
path.push(ln);
}
protected NT pop() {
return path.pop();
}
public boolean allow(NT ln) {
return true;
}
public abstract NT action(NT in);
protected NT performAction(NT in) {
return action(in);
}
protected abstract void traverseInternal(NT n);
protected final NT doAction(NT in) {
if (repeat == ExecStyle.ONCE)
return performAction(in);
else if (repeat == ExecStyle.REPEAT) {
NT c = in;
NT last = null;
do {
last = c;
c = performAction(c);
} while(c != last);
return c;
} else {
throw new SchemaException(Pass.PLANNER, "Unknown execution style for traversal: " + repeat);
}
}
public final NT traverse(NT n) {
if (n == null) return n;
if (!allow(n)) return n;
NT out = null;
push(n);
if (order == Order.PREORDER) {
out = doAction(n);
traverseInternal(out);
} else if (order == Order.POSTORDER || order == Order.NATURAL_ORDER) {
traverseInternal(n);
out = doAction(n);
} else {
throw new MigrationException("Unknown ordering for traversal: " + order);
}
pop();
return out;
}
}