/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB L.L.C.
*
* VoltDB 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.
*
* VoltDB 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 VoltDB. If not, see <http://www.gnu.org/licenses/>.
*/
package org.voltdb.plannodes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONStringer;
import org.voltdb.VoltType;
import org.voltdb.catalog.Database;
import org.voltdb.utils.Pair;
/**
*
*/
public class PlanNodeTree implements JSONString {
public enum Members {
PLAN_NODES, PARAMETERS;
}
protected final List<AbstractPlanNode> m_planNodes;
protected final Map<Integer, AbstractPlanNode> m_idToNodeMap = new HashMap<Integer, AbstractPlanNode>();
protected final List<Pair<Integer, VoltType>> m_parameters = new ArrayList<Pair<Integer, VoltType>>();
public PlanNodeTree() {
m_planNodes = new ArrayList<AbstractPlanNode>();
}
public PlanNodeTree(AbstractPlanNode root_node) {
this();
try {
constructTree(root_node);
} catch (Exception e) {
e.printStackTrace();
}
}
// public void freePlan()
// {
// for (AbstractPlanNode n : m_planNodes)
// {
// n.freeColumns();
// }
// }
public Integer getRootPlanNodeId() {
return m_planNodes.get(0).getPlanNodeId();
}
public AbstractPlanNode getRootPlanNode() {
return m_planNodes.get(0);
}
public Boolean constructTree(AbstractPlanNode node) throws Exception {
m_planNodes.add(node);
m_idToNodeMap.put(node.getPlanNodeId(), node);
for (int i = 0; i < node.getChildPlanNodeCount(); i++) {
AbstractPlanNode child = node.getChild(i);
if (!constructTree(child)) {
return false;
}
}
return true;
}
public List<Pair<Integer, VoltType>> getParameters() {
return m_parameters;
}
public void setParameters(List<Pair<Integer, VoltType>> parameters) {
m_parameters.clear();
m_parameters.addAll(parameters);
}
@Override
public String toJSONString() {
JSONStringer stringer = new JSONStringer();
try {
stringer.object();
toJSONString(stringer);
stringer.endObject();
} catch (JSONException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return stringer.toString();
}
public void toJSONString(JSONStringer stringer) throws JSONException {
stringer.key(Members.PLAN_NODES.name()).array();
for (AbstractPlanNode node : m_planNodes) {
assert (node instanceof JSONString);
stringer.value(node);
}
stringer.endArray(); // end entries
stringer.key(Members.PARAMETERS.name()).array();
for (Pair<Integer, VoltType> parameter : m_parameters) {
stringer.array().value(parameter.getFirst()).value(parameter.getSecond().name()).endArray();
}
stringer.endArray();
}
protected void loadFromJSONObject(JSONObject object, Database db) throws JSONException {
JSONArray planNodes = object.getJSONArray(Members.PLAN_NODES.name());
for (int ii = 0; ii < planNodes.length(); ii++) {
JSONObject jobj = planNodes.getJSONObject(ii);
AbstractPlanNode node = AbstractPlanNode.fromJSONObject(jobj, db);
m_planNodes.add(node);
m_idToNodeMap.put(node.getPlanNodeId(), node);
}
for (AbstractPlanNode node : m_planNodes) {
for (Integer childId : node.m_childrenIds) {
node.m_children.add(m_idToNodeMap.get(childId));
}
for (Integer parentId : node.m_parentIds) {
node.m_parents.add(m_idToNodeMap.get(parentId));
}
}
JSONArray parameters = object.getJSONArray(Members.PARAMETERS.name());
for (int ii = 0; ii < parameters.length(); ii++) {
JSONArray parameter = parameters.getJSONArray(ii);
int index = parameter.getInt(0);
VoltType type = VoltType.typeFromString(parameter.getString(1));
this.m_parameters.add(new Pair<Integer, VoltType>(index, type));
}
// Set<PlanNodeType> types =
// PlanNodeUtil.getPlanNodeTypes(m_planNodes.get(0));
// if (types.contains(PlanNodeType.INSERT) ||
// types.contains(PlanNodeType.UPDATE) ||
// types.contains(PlanNodeType.DELETE)) {
// for (AbstractPlanNode node : m_planNodes) {
// // MOTHER FUCKER!!!
// node.updateOutputColumns(db);
// }
// }
}
public static PlanNodeTree fromJSONObject(JSONObject obj, Database db) throws JSONException {
PlanNodeList list = new PlanNodeList();
list.loadFromJSONObject(obj, db);
return list;
}
}