/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
/**
*
*/
package edu.isi.karma.view.tabledata;
import java.util.LinkedList;
import java.util.List;
import org.json.JSONException;
import org.json.JSONWriter;
import edu.isi.karma.rep.HNode;
import edu.isi.karma.rep.Node;
import edu.isi.karma.view.Margin;
import edu.isi.karma.view.VWorkspace;
import edu.isi.karma.view.tableheadings.VHTreeNode;
/**
* @author szekely
*
*/
public class VDTreeNode {
private final Node node;
private final VHTreeNode vhTreeNode;
private final VDRow containerVDRow;
private final List<VDRow> nestedTableRows = new LinkedList<VDRow>();
/**
* The depth of this tree node. The root table has depth 0.
*/
private int depth = 0;
/**
* If there is a nested table, record the style of margin that will be shown
* above and below.
*/
private Margin margin = null;
/**
* List of margins from all containers, ordered from top to bottom.
*/
private final List<Margin> allMargins = new LinkedList<Margin>();
/**
* Number of levels of data needed to show this node.
*/
private int numLevels = -1;
/**
* The level where this node (if a leaf) or the nested tables will start.
* Zero based.
*/
private int startLevel = -1;
public VDTreeNode(Node node, VHTreeNode vhTreeNode, VDRow containerVDRow) {
super();
this.node = node;
this.vhTreeNode = vhTreeNode;
this.containerVDRow = containerVDRow;
}
public List<VDRow> getNestedTableRows() {
return nestedTableRows;
}
public boolean hasNestedTable() {
return !nestedTableRows.isEmpty();
}
int getDepth() {
return depth;
}
void setDepth(int depth) {
this.depth = depth;
}
Node getNode() {
return node;
}
Margin getMargin() {
return margin;
}
int getNumLevels() {
return numLevels;
}
int getStartLevel() {
return startLevel;
}
int getLastLevel() {
return startLevel + numLevels - 1;
}
void setStartLevel(int startLevel) {
this.startLevel = startLevel;
}
List<Margin> getAllMargins() {
return allMargins;
}
HNode getHNode(VWorkspace vWorkspace) {
return vWorkspace.getRepFactory().getHNode(node.getHNodeId());
}
boolean isFirst() {
return vhTreeNode.isFirst();
}
boolean isLast() {
return vhTreeNode.isLast();
}
boolean isMiddle() {
return vhTreeNode.isMiddle();
}
/**
* @param vWorkspace
* @return if this is a leaf node, then the HTableId of the containing
* HTable. If this is a nested table, then it is the HTableId of the
* parent table of the nested table.
*/
String getContainerHTableId(VWorkspace vWorkspace) {
return getHNode(vWorkspace).getHTableId();
}
void firstPassTopDown(VWorkspace vWorkspace) {
depth = containerVDRow.getDepth();
allMargins.addAll(containerVDRow.getAllMargins());
if (hasNestedTable()) {
margin = new Margin(getContainerHTableId(vWorkspace), depth);
allMargins.add(margin);
}
// Now go top down.
for (VDRow r : nestedTableRows) {
r.setFillHTableId(getHNode(vWorkspace).getNestedTable().getId());
r.firstPassTopDown(vWorkspace);
}
}
void secondPassBottomUp(VWorkspace vWorkspace) {
// First recurse.
for (VDRow r : nestedTableRows) {
r.secondPassBottomUp(vWorkspace);
}
if (containerVDRow != null) {
// Propagate the margin up.
containerVDRow.accumulateMargin(margin);
}
// Calculate numLevels.
if (hasNestedTable()) {
int totalLevels = 0;
for (VDRow r : nestedTableRows) {
totalLevels += r.getNumLevels();
}
numLevels = totalLevels;
} else {
numLevels = 1;
}
}
void thirdPassTopDown(VWorkspace vWorkspace) {
// Now go top down.
int currentLevel = startLevel;
for (VDRow r : nestedTableRows) {
r.setStartLevel(currentLevel);
currentLevel += r.getNumLevels();
r.thirdPassTopDown(vWorkspace);
}
}
/*****************************************************************
*
* Debugging Support
*
*****************************************************************/
void prettyPrintJson(JSONWriter jw, boolean verbose) throws JSONException {
jw.object()//
.key("__node").value(node.toString())//
.key("_depth").value(depth)//
.key("_margin").value(Margin.getMarginsString(margin))//
.key("_allMargins").value(Margin.toString(allMargins))//
.key("_numLevels").value(numLevels)//
.key("_startLevel").value(startLevel)//
;
if (verbose) {
jw.key("hTreeNode");
vhTreeNode.prettyPrintJson(jw, false, false);
}
if (!nestedTableRows.isEmpty()) {
jw.key("rows").array();
for (VDRow r : nestedTableRows) {
r.prettyPrintJson(jw, verbose);
}
jw.endArray();
}
jw.endObject();
}
}