package com.AsamiOffice.util; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Stack; /** * TreeTable * * @since Sep. 30, 2005 * @version Oct. 12, 2005 * @author ASAMI, Tomoharu (asami@relaxer.org) */ public class TreeTable { private RTNode root_ = new RTNode(); private transient D2Array coarseTable_; private transient D2Array rowspanTable_; private transient D2Array colspanTable_; public D2Array getCoarseTable() { ensure_(); return coarseTable_; } public D2Array getDenseTable() { throw new UnsupportedOperationException(); } public D2Array getRowSpanTable() { ensure_(); return rowspanTable_; } public String[] getLeafPathNames() { LeafPathNameMaker maker = new LeafPathNameMaker(); root_.traverse(maker); return maker.getNames(); } public D2Array getColSpanTable() { ensure_(); return colspanTable_; } public int getWidth() { ensure_(); return coarseTable_.getWidth(); } public int getHeight() { ensure_(); return coarseTable_.getHeight(); } private void ensure_() { if (coarseTable_ != null) { return; } CoarseTableMaker maker = new CoarseTableMaker(); coarseTable_ = maker.getTable(); rowspanTable_ = new D2Array(); colspanTable_ = new D2Array(); int height = coarseTable_.getHeight(); int width = coarseTable_.getWidth(); for (int y = 0;y < height;y++) { for (int x = 0;x < width;x++) { if (coarseTable_.get(x, y) == null) { rowspanTable_.put(x, y, null); colspanTable_.put(x, y, null); } else { rowspanTable_.put(x, y, calcRowspan_(x, y, height)); colspanTable_.put(x, y, calcColspan_(x, y, width)); } } } } private Integer calcRowspan_(int x, int y, int height) { int count = 1; for (int i = y + 1;i < height;i++) { if (coarseTable_.get(x, i) != null) { break; } count++; } return Integer.valueOf(count); } private Integer calcColspan_(int x, int y, int width) { int count = 1; for (int i = x + 1;i < width;i++) { if (coarseTable_.get(i, y) != null) { break; } count++; } return Integer.valueOf(count); } public Cursor getCursor() { return new Cursor(root_); } public class Cursor { private RTNode current_; private RTNode parent_; private Stack stack_ = new Stack(); public Cursor(RTNode root) { parent_ = root; current_ = null; } public void add(Object data) { current_ = new RTNode(data); parent_.add(current_); } public void enter() { parent_ = current_; push_(); } public void leave() { pop_(); parent_ = current_.parent_; } private void push_() { stack_.push(current_); current_ = null; } private void pop_() { current_ = (RTNode)stack_.pop(); } } public class RTNode { private Object data_; private RTNode parent_; private List children_ = new ArrayList(); public RTNode(Object data) { data_ = data; } public RTNode() { } public Object getData() { return data_; } public void add(RTNode node) { children_.add(node); node.parent_ = this; } public void traverse(IRTVisitor visitor) { Object[] children = children_.toArray(); for (int i = 0;i < children.length;i++) { RTNode node = (RTNode)children[i]; visitor.enter(node); node.traverse(visitor); visitor.leave(node); } } public boolean isFirstNode() { return parent_.children_.get(0) == this; } } public interface IRTVisitor { // void start(RTNode node); // void end(RTNode node); void enter(RTNode node); // void stay(RTNode node, RTNode prev, RTNode next); void leave(RTNode node); } public abstract class AbstractRTVisitor implements IRTVisitor { } public class CoarseTableMaker extends AbstractRTVisitor { private D2Array array_ = new D2Array(); private int y_ = 0; private XHolder xHolder_ = new XHolder(); public D2Array getTable() { root_.traverse(this); return array_; } public void enter(RTNode node) { array_.put(xHolder_.count(node), y_, node.getData()); y_++; } public void leave(RTNode node) { y_--; } class XHolder { int count_ = 0; public int count(RTNode node) { if (node.isFirstNode()) { return count_; } else { return ++count_; } } } } public class LeafPathNameMaker extends AbstractRTVisitor { List names_ = new ArrayList(); public String[] getNames() { String[] result = new String[names_.size()]; return (String[])names_.toArray(result); } public void enter(RTNode node) { if (node.children_.size() == 0) { LinkedList list = new LinkedList(); while (node != root_) { list.add(node.data_.toString()); node = node.parent_; } StringBuffer sb = new StringBuffer(); String name = (String)list.removeLast(); sb.append(name); while (!list.isEmpty()) { name = (String)list.removeLast(); sb.append('/'); sb.append(name); } names_.add(sb.toString()); } } public void leave(RTNode node) { } } }