weka.gui.treevisualizer.TreeBuild Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-dev Show documentation
Show all versions of weka-dev Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This version represents the developer version, the
"bleeding edge" of development, you could say. New functionality gets added
to this version.
/*
* This program 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.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* TreeBuild.java
* Copyright (C) 1999-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.gui.treevisualizer;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.util.Hashtable;
import java.util.Vector;
/**
* This class will parse a dotty file and construct a tree structure from it
* with Edge's and Node's
*
* @author Malcolm Ware ([email protected])
* @version $Revision: 14489 $
*/
public class TreeBuild {
// this class will parse the tree into relevant strings
// into info objects
// from there it will create the nodes and edges from the info objects
/** The name of the tree, Not in use. */
// private String m_graphName; NOT USED
/** An array with all the nodes initially constructed into it. */
private Vector m_aNodes;
/** An array with all the edges initially constructed into it. */
private Vector m_aEdges;
/**
* An array containing a structure that describes the node without actually
* creating it.
*/
private Vector m_nodes;
/**
* An arry containing a structure that describes the edge without actually
* creating it.
*/
private Vector m_edges;
/** An object setup to take graph data. */
private InfoObject m_grObj;
/** An object setup to take node data. */
private InfoObject m_noObj;
/** An object setup to take edge data. */
private InfoObject m_edObj;
/** true if it is a digraph. (note that this can't build digraphs). */
// private boolean m_digraph; NOT USED
/** The stream to parse. */
private StreamTokenizer m_st;
/** A table containing all the colors. */
private final Hashtable m_colorTable;
/**
* Upon construction this will only setup the color table for quick reference
* of a color.
*/
public TreeBuild() {
m_colorTable = new Hashtable();
Colors ab = new Colors();
for (NamedColor m_col : ab.m_cols) {
m_colorTable.put(m_col.m_name, m_col.m_col);
}
}
/**
* This will build A node structure from the dotty format passed. Don't send a
* dotty format with multiple parents per node, and ensure that there is 1 and
* only 1 node with no parent.
*
* @param t The reader with the dotty string to be read.
* @return The top node of the tree structure (the last node with no parent).
*/
public Node create(Reader t) {
m_nodes = new Vector(50, 50);
m_edges = new Vector(50, 50);
m_grObj = new InfoObject("graph");
m_noObj = new InfoObject("node");
m_edObj = new InfoObject("edge");
// m_digraph = false; NOT USED
m_st = new StreamTokenizer(new BufferedReader(t));
setSyntax();
graph();
Node top = generateStructures();
return top;
}
/**
* This will go through all the found Nodes and Edges build instances of these
* and link them together.
*
* @return The node with no parent (the top of the tree).
*/
private Node generateStructures() {
String id, label; // ,source,target; NOT USED
Integer shape, style;
// int fontsize; NOT USED
Color fontcolor, color;
InfoObject t;
m_aNodes = new Vector(50, 50);
m_aEdges = new Vector(50, 50);
for (int noa = 0; noa < m_nodes.size(); noa++) {
t = m_nodes.elementAt(noa);
id = t.m_id;
if (t.m_label == null) {
if (m_noObj.m_label == null) {
label = "";
} else {
label = m_noObj.m_label;
}
} else {
label = t.m_label;
}
if (t.m_shape == null) {
if (m_noObj.m_shape == null) {
shape = new Integer(2);
} else {
shape = getShape(m_noObj.m_shape);
}
} else {
shape = getShape(t.m_shape);
}
if (shape == null) {
shape = new Integer(2);
}
if (t.m_style == null) {
if (m_noObj.m_style == null) {
style = new Integer(1);
} else {
style = getStyle(m_noObj.m_style);
}
} else {
style = getStyle(t.m_style);
}
if (style == null) {
style = new Integer(1);
}
/*
* NOT USED if (t.m_fontSize == null) { if (m_noObj.m_fontSize == null) {
* fontsize = 12; } else { fontsize =
* Integer.valueOf(m_noObj.m_fontSize).intValue(); } } else { fontsize =
* Integer.valueOf(t.m_fontSize).intValue(); }
*/
if (t.m_fontColor == null) {
if (m_noObj.m_fontColor == null) {
fontcolor = Color.black;
} else {
fontcolor = m_colorTable.get(m_noObj.m_fontColor.toLowerCase());
}
} else {
fontcolor = m_colorTable.get(t.m_fontColor.toLowerCase());
}
if (fontcolor == null) {
fontcolor = Color.black;
}
if (t.m_color == null) {
if (m_noObj.m_color == null) {
color = Color.lightGray;
} else {
color = m_colorTable.get(m_noObj.m_color.toLowerCase());
}
} else {
color = m_colorTable.get(t.m_color.toLowerCase());
}
if (color == null) {
color = Color.lightGray;
}
m_aNodes.addElement(new Node(label, id, style.intValue(), shape
.intValue(), color, t.m_data));
}
for (int noa = 0; noa < m_edges.size(); noa++) {
t = m_edges.elementAt(noa);
id = t.m_id;
if (t.m_label == null) {
if (m_noObj.m_label == null) {
label = "";
} else {
label = m_noObj.m_label;
}
} else {
label = t.m_label;
}
if (t.m_shape == null) {
if (m_noObj.m_shape == null) {
shape = new Integer(2);
} else {
shape = getShape(m_noObj.m_shape);
}
} else {
shape = getShape(t.m_shape);
}
if (shape == null) {
shape = new Integer(2);
}
if (t.m_style == null) {
if (m_noObj.m_style == null) {
style = new Integer(1);
} else {
style = getStyle(m_noObj.m_style);
}
} else {
style = getStyle(t.m_style);
}
if (style == null) {
style = new Integer(1);
}
/*
* NOT USED if (t.m_fontSize == null) { if (m_noObj.m_fontSize == null) {
* fontsize = 12; NOT USEDa } else { fontsize =
* Integer.valueOf(m_noObj.m_fontSize).intValue(); NOT USED } } else {
* fontsize = Integer.valueOf(t.m_fontSize).intValue(); }
*/
if (t.m_fontColor == null) {
if (m_noObj.m_fontColor == null) {
fontcolor = Color.black;
} else {
fontcolor = m_colorTable.get(m_noObj.m_fontColor.toLowerCase());
}
} else {
fontcolor = m_colorTable.get(t.m_fontColor.toLowerCase());
}
if (fontcolor == null) {
fontcolor = Color.black;
}
if (t.m_color == null) {
if (m_noObj.m_color == null) {
color = Color.white;
} else {
color = m_colorTable.get(m_noObj.m_color.toLowerCase());
}
} else {
color = m_colorTable.get(t.m_color.toLowerCase());
}
if (color == null) {
color = Color.white;
}
m_aEdges.addElement(new Edge(label, t.m_source, t.m_target));
}
boolean f_set, s_set;
Node x, sour = null, targ = null;
Edge y;
for (int noa = 0; noa < m_aEdges.size(); noa++) {
f_set = false;
s_set = false;
y = m_aEdges.elementAt(noa);
for (int nob = 0; nob < m_aNodes.size(); nob++) {
x = m_aNodes.elementAt(nob);
if (x.getRefer().equals(y.getRtarget())) {
f_set = true;
targ = x;
}
if (x.getRefer().equals(y.getRsource())) {
s_set = true;
sour = x;
}
if (f_set == true && s_set == true) {
break;
}
}
if (targ != sour) {
y.setTarget(targ);
y.setSource(sour);
} else {
System.out.println("logic error");
}
}
for (int noa = 0; noa < m_aNodes.size(); noa++) {
if (m_aNodes.elementAt(noa).getParent(0) == null) {
sour = m_aNodes.elementAt(noa);
}
}
return sour;
}
/**
* This will convert the shape string to an int representing that shape.
*
* @param sh The name of the shape.
* @return An Integer representing the shape.
*/
private Integer getShape(String sh) {
if (sh.equalsIgnoreCase("box") || sh.equalsIgnoreCase("rectangle")) {
return new Integer(1);
} else if (sh.equalsIgnoreCase("oval")) {
return new Integer(2);
} else if (sh.equalsIgnoreCase("diamond")) {
return new Integer(3);
} else {
return null;
}
}
/**
* Converts the string representing the fill style int oa number representing
* it.
*
* @param sty The name of the style.
* @return An Integer representing the shape.
*/
private Integer getStyle(String sty) {
if (sty.equalsIgnoreCase("filled")) {
return new Integer(1);
} else {
return null;
}
}
/**
* This will setup the syntax for the tokenizer so that it parses the string
* properly.
*
*/
private void setSyntax() {
m_st.resetSyntax();
m_st.eolIsSignificant(false);
m_st.slashStarComments(true);
m_st.slashSlashComments(true);
// System.out.println("slash");
m_st.whitespaceChars(0, ' ');
m_st.wordChars(' ' + 1, '\u00ff');
m_st.ordinaryChar('[');
m_st.ordinaryChar(']');
m_st.ordinaryChar('{');
m_st.ordinaryChar('}');
m_st.ordinaryChar('-');
m_st.ordinaryChar('>');
m_st.ordinaryChar('/');
m_st.ordinaryChar('*');
m_st.quoteChar('"');
m_st.whitespaceChars(';', ';');
m_st.ordinaryChar('=');
}
/**
* This is the alternative syntax for the tokenizer.
*/
private void alterSyntax() {
m_st.resetSyntax();
m_st.wordChars('\u0000', '\u00ff');
m_st.slashStarComments(false);
m_st.slashSlashComments(false);
m_st.ordinaryChar('\n');
m_st.ordinaryChar('\r');
}
/**
* This will parse the next token out of the stream and check for certain
* conditions.
*
* @param r The error string to print out if something goes wrong.
*/
private void nextToken(String r) {
int t = 0;
try {
t = m_st.nextToken();
} catch (IOException e) {
}
if (t == StreamTokenizer.TT_EOF) {
System.out.println("eof , " + r);
} else if (t == StreamTokenizer.TT_NUMBER) {
System.out.println("got a number , " + r);
}
}
/**
* Parses the top of the dotty stream that has the graph information.
*
*/
private void graph() {
nextToken("expected 'digraph'");
if (m_st.sval.equalsIgnoreCase("digraph")) {
// m_digraph = true; NOT USED
} else {
System.out.println("expected 'digraph'");
}
nextToken("expected a Graph Name");
if (m_st.sval != null) {
// m_graphName = m_st.sval; NOT USED
} else {
System.out.println("expected a Graph Name");
}
nextToken("expected '{'");
if (m_st.ttype == '{') {
stmtList();
} else {
System.out.println("expected '{'");
}
}
/**
* This is one of the states, this one is where new items can be defined or
* the structure can end.
*
*/
private void stmtList() {
boolean flag = true;
while (flag) {
nextToken("expects a STMT_LIST item or '}'");
if (m_st.ttype == '}') {
flag = false;
} else if (m_st.sval.equalsIgnoreCase("graph")
|| m_st.sval.equalsIgnoreCase("node")
|| m_st.sval.equalsIgnoreCase("edge")) {
m_st.pushBack();
attrStmt();
} else {
nodeId(m_st.sval, 0);
}
}
}
/**
* This will deal specifically with a new object such as graph , node , edge.
*
*/
private void attrStmt() {
nextToken("expected 'graph' or 'node' or 'edge'");
if (m_st.sval.equalsIgnoreCase("graph")) {
nextToken("expected a '['");
if (m_st.ttype == '[') {
attrList(m_grObj);
} else {
System.out.println("expected a '['");
}
} else if (m_st.sval.equalsIgnoreCase("node")) {
nextToken("expected a '['");
if (m_st.ttype == '[') {
attrList(m_noObj);
} else {
System.out.println("expected a '['");
}
} else if (m_st.sval.equalsIgnoreCase("edge")) {
nextToken("expected a '['");
if (m_st.ttype == '[') {
attrList(m_edObj);
} else {
System.out.println("expected a '['");
}
} else {
System.out.println("expected 'graph' or 'node' or 'edge'");
}
}
/**
* Generates a new InfoObject with the specified name and either does further
* processing if applicable Otherwise it is an edge and will deal with that.
*
* @param s The ID string.
* @param t Not sure!.
*/
private void nodeId(String s, int t) {
nextToken("error occurred in node_id");
if (m_st.ttype == '}') {
// creates a node if t is zero
if (t == 0) {
m_nodes.addElement(new InfoObject(s));
}
m_st.pushBack();
} else if (m_st.ttype == '-') {
nextToken("error occurred checking for an edge");
if (m_st.ttype == '>') {
edgeStmt(s);
} else {
System.out.println("error occurred checking for an edge");
}
} else if (m_st.ttype == '[') {
// creates a node if t is zero and sends it to attr
if (t == 0) {
m_nodes.addElement(new InfoObject(s));
attrList(m_nodes.lastElement());
} else {
attrList(m_edges.lastElement());
}
} else if (m_st.sval != null) {
// creates a node if t is zero
if (t == 0) {
m_nodes.addElement(new InfoObject(s));
}
m_st.pushBack();
} else {
System.out.println("error occurred in node_id");
}
}
/**
* This will get the target of the edge.
*
* @param i The source of the edge.
*/
private void edgeStmt(String i) {
nextToken("error getting target of edge");
if (m_st.sval != null) {
m_edges.addElement(new InfoObject("an edge ,no id"));
m_edges.lastElement().m_source = i;
m_edges.lastElement().m_target = m_st.sval;
nodeId(m_st.sval, 1);
} else {
System.out.println("error getting target of edge");
}
}
/**
* This will parse all the items in the attrib list for an object.
*
* @param a The object that the attribs apply to.
*/
private void attrList(InfoObject a) {
boolean flag = true;
while (flag) {
nextToken("error in attr_list");
// System.out.println(st.sval);
if (m_st.ttype == ']') {
flag = false;
} else if (m_st.sval.equalsIgnoreCase("color")) {
nextToken("error getting color");
if (m_st.ttype == '=') {
nextToken("error getting color");
if (m_st.sval != null) {
a.m_color = m_st.sval;
} else {
System.out.println("error getting color");
}
} else {
System.out.println("error getting color");
}
} else if (m_st.sval.equalsIgnoreCase("fontcolor")) {
nextToken("error getting font color");
if (m_st.ttype == '=') {
nextToken("error getting font color");
if (m_st.sval != null) {
a.m_fontColor = m_st.sval;
} else {
System.out.println("error getting font color");
}
} else {
System.out.println("error getting font color");
}
} else if (m_st.sval.equalsIgnoreCase("fontsize")) {
nextToken("error getting font size");
if (m_st.ttype == '=') {
nextToken("error getting font size");
if (m_st.sval != null) {
} else {
System.out.println("error getting font size");
}
} else {
System.out.println("error getting font size");
}
} else if (m_st.sval.equalsIgnoreCase("label")) {
nextToken("error getting label");
if (m_st.ttype == '=') {
nextToken("error getting label");
if (m_st.sval != null) {
a.m_label = m_st.sval;
} else {
System.out.println("error getting label");
}
} else {
System.out.println("error getting label");
}
} else if (m_st.sval.equalsIgnoreCase("shape")) {
nextToken("error getting shape");
if (m_st.ttype == '=') {
nextToken("error getting shape");
if (m_st.sval != null) {
a.m_shape = m_st.sval;
} else {
System.out.println("error getting shape");
}
} else {
System.out.println("error getting shape");
}
} else if (m_st.sval.equalsIgnoreCase("style")) {
nextToken("error getting style");
if (m_st.ttype == '=') {
nextToken("error getting style");
if (m_st.sval != null) {
a.m_style = m_st.sval;
} else {
System.out.println("error getting style");
}
} else {
System.out.println("error getting style");
}
} else if (m_st.sval.equalsIgnoreCase("data")) {
nextToken("error getting data");
if (m_st.ttype == '=') {
// data has a special data string that can have anything
// this is delimited by a single comma on an otherwise empty line
alterSyntax();
a.m_data = new String("");
while (true) {
nextToken("error getting data");
if (m_st.sval != null && a.m_data != null && m_st.sval.equals(",")) {
break;
} else if (m_st.sval != null) {
a.m_data = a.m_data.concat(m_st.sval);
} else if (m_st.ttype == '\r') {
a.m_data = a.m_data.concat("\r");
} else if (m_st.ttype == '\n') {
a.m_data = a.m_data.concat("\n");
} else {
System.out.println("error getting data");
}
}
setSyntax();
} else {
System.out.println("error getting data");
}
}
}
}
// special class for use in creating the tree
/**
* This is an internal class used to keep track of the info for the objects
* before they are actually created.
*/
private class InfoObject {
/** The ID string for th object. */
public String m_id;
/** The color name for the object. */
public String m_color;
/** The font color for the object. not in use. */
public String m_fontColor;
/** The label for the object. */
public String m_label;
/** The shape name of for the object. */
public String m_shape;
/** The backstyle name for the object. */
public String m_style;
/** The source ID of the object. */
public String m_source;
/** The target ID of the object. */
public String m_target;
/** The data for this object. */
public String m_data;
/**
* This will construct a new InfoObject with the specified ID string.
*/
public InfoObject(String i) {
m_id = i;
m_color = null;
m_fontColor = null;
m_label = null;
m_shape = null;
m_style = null;
m_source = null;
m_target = null;
m_data = null;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy