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-stable Show documentation
Show all versions of weka-stable Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This is the stable version. Apart from bugfixes, this version
does not receive any other updates.
/*
* 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: 9097 $
*/
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;
/** 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;
/** The stream to parse. */
private StreamTokenizer m_st;
/** A table containing all the colors. */
private 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 (int noa = 0;noa < ab.m_cols.length;noa++) {
m_colorTable.put(ab.m_cols[noa].m_name,ab.m_cols[noa].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;
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;
Integer shape,style;
int fontsize;
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 = (InfoObject)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);
}
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 = (Color)m_colorTable
.get(m_noObj.m_fontColor.toLowerCase());
}
}
else {
fontcolor = (Color)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.gray;
}
else {
color = (Color)m_colorTable.get(m_noObj.m_color.toLowerCase());
}
}
else {
color = (Color)m_colorTable.get(t.m_color.toLowerCase());
}
if (color == null) {
color = Color.gray;
}
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 = (InfoObject)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);
}
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 = (Color)m_colorTable
.get(m_noObj.m_fontColor.toLowerCase());
}
}
else {
fontcolor = (Color)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 = (Color)m_colorTable.get(m_noObj.m_color.toLowerCase());
}
}
else {
color = (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 = (Edge)m_aEdges.elementAt(noa);
for (int nob = 0;nob < m_aNodes.size();nob++) {
x = (Node)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 (((Node)m_aNodes.elementAt(noa)).getParent(0) == null) {
sour = (Node)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 == m_st.TT_EOF) {
System.out.println("eof , " + r);
}
else if (t == m_st.TT_NUMBER) {
System.out.println("got a number , " + r);
}
}
/**
* Parses the top of the dotty stream that has the graph information.
*
*/
private void graph() {
boolean flag = true;
String s;
//expect digraph
int t;
nextToken("expected 'digraph'");
if (m_st.sval.equalsIgnoreCase("digraph")) {
m_digraph = true;
}
else {
System.out.println("expected 'digraph'");
}
nextToken("expected a Graph Name");
if (m_st.sval != null) {
m_graphName = m_st.sval;
}
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;
String s;
int t;
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 if (m_st.sval != null) {
nodeId(m_st.sval,0);
}
else {
System.out.println("expects a STMT_LIST item or '}'");
}
}
}
/**
* 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((InfoObject)m_nodes.lastElement());
}
else {
attrList((InfoObject)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"));
((InfoObject)m_edges.lastElement()).m_source = i;
((InfoObject)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) {
a.m_fontSize = m_st.sval;
}
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 fontsize for the object. not in use. */
public String m_fontSize;
/** 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_fontSize = null;
m_label = null;
m_shape = null;
m_style = null;
m_source = null;
m_target = null;
m_data = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy