TreeBuild.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 19k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    Tree_build.java
  18.  *    Copyright (C) 1999 Malcolm Ware
  19.  *
  20.  */
  21. package weka.gui.treevisualizer;
  22. import java.util.*;
  23. import java.io.*;
  24. import java.awt.*;
  25. /**
  26.  * This class will parse a dotty file and construct a tree structure from it 
  27.  * with Edge's and Node's
  28.  *
  29.  * @author Malcolm Ware (mfw4@cs.waikato.ac.nz)
  30.  * @version $Revision: 1.3 $
  31.  */
  32. public class TreeBuild {
  33.   //this class will parse the tree into relevant strings
  34.   //into info objects 
  35.   //from there it will create the nodes and edges from the info objects
  36.   /** The name of the tree, Not in use. */
  37.   private String m_graphName;
  38.   /** An array with all the nodes initially constructed into it. */
  39.   private Vector m_aNodes;
  40.   /** An array with all the edges initially constructed into it. */
  41.   private Vector m_aEdges;
  42.   /** An array containing a structure that describes the node without 
  43.    * actually creating it. */
  44.   private Vector m_nodes;
  45.   /** An arry containing a structure that describes the edge without 
  46.    * actually creating it. */
  47.   private Vector m_edges;
  48.   /** An object setup to take graph data. */
  49.   private InfoObject m_grObj;
  50.   /** An object setup to take node data. */
  51.   private InfoObject m_noObj;
  52.   /** An object setup to take edge data. */
  53.   private InfoObject m_edObj;
  54.   /** true if it is a digraph. (note that this can't build digraphs). */
  55.   private boolean m_digraph;
  56.   
  57.   /** The stream to parse. */
  58.   private StreamTokenizer m_st;
  59.   /** A table containing all the colors. */
  60.   private Hashtable m_colorTable;
  61.   
  62.   /**
  63.    * Upon construction this will only setup the color table for quick 
  64.    * reference of a color.
  65.    */
  66.   public TreeBuild() {
  67.     m_colorTable = new Hashtable();
  68.     
  69.     Colors ab = new Colors();
  70.     for (int noa = 0;noa < ab.m_cols.length;noa++) {
  71.       m_colorTable.put(ab.m_cols[noa].m_name,ab.m_cols[noa].m_col);
  72.     }
  73.   }  
  74.     
  75.   /**
  76.    * This will build A node structure from the dotty format passed. Don't 
  77.    * send a dotty format with multiple parents
  78.    * per node, and ensure that there is 1 and only 1 node with no parent.
  79.    *
  80.    * @param t The reader with the dotty string to be read.
  81.    * @return The top node of the tree structure (the last node with no parent).
  82.    */
  83.   public Node create(Reader t) {
  84.     m_nodes = new Vector(50,50);
  85.     m_edges = new Vector(50,50);
  86.     m_grObj = new InfoObject("graph");
  87.     m_noObj = new InfoObject("node");
  88.     m_edObj = new InfoObject("edge");
  89.     m_digraph = false;
  90.     
  91.     m_st = new StreamTokenizer(new BufferedReader(t));
  92.     setSyntax();
  93.     graph();
  94.     Node top = generateStructures();
  95.     
  96.     return top;
  97.   }
  98.   
  99.   /**
  100.    * This will go through all the found Nodes and Edges build instances of 
  101.    * these
  102.    * and link them together.
  103.    *
  104.    * @return The node with no parent (the top of the tree).
  105.    */
  106.   private Node generateStructures() {
  107.     String id,label,source,target;
  108.     Integer shape,style;
  109.     int fontsize;
  110.     Color fontcolor,color;
  111.     InfoObject t;
  112.     m_aNodes = new Vector(50,50);
  113.     m_aEdges = new Vector(50,50);
  114.     for (int noa = 0;noa < m_nodes.size();noa++) {
  115.       t = (InfoObject)m_nodes.elementAt(noa);
  116.       id = t.m_id;
  117.       
  118.       if (t.m_label == null) {
  119. if (m_noObj.m_label == null) {
  120.   label = "";
  121. }
  122. else {
  123.   label = m_noObj.m_label;
  124. }
  125.       }
  126.       else {
  127. label = t.m_label;
  128.       }
  129.       
  130.       if (t.m_shape == null) {
  131. if (m_noObj.m_shape == null) {
  132.   shape = new Integer(2);
  133. }
  134. else {
  135.   shape = getShape(m_noObj.m_shape);
  136. }
  137.       }
  138.       else {
  139. shape = getShape(t.m_shape);
  140.       }
  141.       if (shape == null) {
  142. shape = new Integer(2);
  143.       }
  144.       
  145.       if (t.m_style == null) {
  146. if (m_noObj.m_style == null) {
  147.   style = new Integer(1);
  148. }
  149. else {
  150.   style = getStyle(m_noObj.m_style);
  151. }
  152.       }
  153.       else {
  154. style = getStyle(t.m_style);
  155.       }
  156.       if (style == null) {
  157. style = new Integer(1);
  158.       }
  159.       
  160.       if (t.m_fontSize == null) {
  161. if (m_noObj.m_fontSize == null) {
  162.   fontsize = 12;
  163. }
  164. else {
  165.   fontsize = Integer.valueOf(m_noObj.m_fontSize).intValue();
  166. }
  167.       }
  168.       else {
  169. fontsize = Integer.valueOf(t.m_fontSize).intValue();
  170.       }
  171.       
  172.       if (t.m_fontColor == null) {
  173. if (m_noObj.m_fontColor == null) {
  174.   fontcolor = Color.black;
  175. }
  176. else {
  177.   fontcolor = (Color)m_colorTable
  178.     .get(m_noObj.m_fontColor.toLowerCase());
  179. }
  180.       }
  181.       else {
  182. fontcolor = (Color)m_colorTable.get(t.m_fontColor.toLowerCase());
  183.       }
  184.       if (fontcolor == null) {
  185. fontcolor = Color.black;
  186.       }
  187.       
  188.       if (t.m_color == null) {
  189. if (m_noObj.m_color == null) {
  190.   color = Color.gray;
  191. }
  192. else {
  193.   color = (Color)m_colorTable.get(m_noObj.m_color.toLowerCase());
  194. }
  195.       }
  196.       else {
  197. color = (Color)m_colorTable.get(t.m_color.toLowerCase());
  198.       }
  199.       if (color == null) {
  200. color = Color.gray;
  201.       }
  202.       
  203.       m_aNodes.addElement(new Node(label,id,style.intValue(),shape.intValue(),
  204.   color,t.m_data));
  205.     }
  206.     for (int noa = 0;noa < m_edges.size();noa++) {
  207.       t = (InfoObject)m_edges.elementAt(noa);
  208.       id = t.m_id;
  209.       
  210.       if (t.m_label == null) {
  211. if (m_noObj.m_label == null) {
  212.   label = "";
  213. }
  214. else {
  215.   label = m_noObj.m_label;
  216. }
  217.       }
  218.       else {
  219. label = t.m_label;
  220.       }
  221.       
  222.       if (t.m_shape == null) {
  223. if (m_noObj.m_shape == null) {
  224.   shape = new Integer(2);
  225. }
  226. else {
  227.   shape = getShape(m_noObj.m_shape);
  228. }
  229.       }
  230.       else {
  231. shape = getShape(t.m_shape);
  232.       }
  233.       if (shape == null) {
  234. shape = new Integer(2);
  235.       }
  236.       
  237.       if (t.m_style == null) {
  238. if (m_noObj.m_style == null) {
  239.   style = new Integer(1);
  240. }
  241. else {
  242.   style = getStyle(m_noObj.m_style);
  243. }
  244.       }
  245.       else {
  246. style = getStyle(t.m_style);
  247.       }
  248.       if (style == null) {
  249. style = new Integer(1);
  250.       }
  251.       
  252.       if (t.m_fontSize == null) {
  253. if (m_noObj.m_fontSize == null) {
  254.   fontsize = 12;
  255. }
  256. else {
  257.   fontsize = Integer.valueOf(m_noObj.m_fontSize).intValue();
  258. }
  259.       }
  260.       else {
  261. fontsize = Integer.valueOf(t.m_fontSize).intValue();
  262.       }
  263.       
  264.       if (t.m_fontColor == null) {
  265. if (m_noObj.m_fontColor == null) {
  266.   fontcolor = Color.black;
  267. }
  268. else {
  269.   fontcolor = (Color)m_colorTable
  270.     .get(m_noObj.m_fontColor.toLowerCase());
  271. }
  272.       }
  273.       else {
  274. fontcolor = (Color)m_colorTable.get(t.m_fontColor.toLowerCase());
  275.       }
  276.       if (fontcolor == null) {
  277. fontcolor = Color.black;
  278.       }
  279.       
  280.       if (t.m_color == null) {
  281. if (m_noObj.m_color == null) {
  282.   color = Color.white;
  283. }
  284. else {
  285.   color = (Color)m_colorTable.get(m_noObj.m_color.toLowerCase());
  286. }
  287.       }
  288.       else {
  289. color = (Color)m_colorTable.get(t.m_color.toLowerCase());
  290.       }
  291.       if (color == null) {
  292. color = Color.white;
  293.       }
  294.       
  295.       m_aEdges.addElement(new Edge(label,t.m_source,t.m_target));
  296.     }
  297.         
  298.     boolean f_set,s_set;
  299.     Node x,sour = null,targ = null;
  300.     Edge y;
  301.     for (int noa = 0;noa < m_aEdges.size();noa++) {
  302.       f_set = false;
  303.       s_set = false;
  304.       y = (Edge)m_aEdges.elementAt(noa);
  305.       for (int nob = 0;nob < m_aNodes.size();nob++) {
  306. x = (Node)m_aNodes.elementAt(nob);
  307. if (x.getRefer().equals(y.getRtarget())) {
  308.   f_set = true;
  309.   targ = x;
  310. }
  311. if (x.getRefer().equals(y.getRsource())) {
  312.   s_set = true;
  313.   sour = x;
  314. }
  315. if (f_set == true && s_set == true) {
  316.   break;
  317. }
  318.       }
  319.       if (targ != sour) {
  320. y.setTarget(targ);
  321. y.setSource(sour);
  322.       }
  323.       else {
  324. System.out.println("logic error");
  325.       }
  326.     }
  327.     
  328.     for (int noa = 0;noa < m_aNodes.size();noa++) {
  329.       if (((Node)m_aNodes.elementAt(noa)).getParent(0) == null) {
  330. sour = (Node)m_aNodes.elementAt(noa);
  331.       }
  332.     }
  333.     return sour;
  334.   }
  335.   
  336.   /**
  337.    * This will convert the shape string to an int representing that shape.
  338.    *
  339.    * @param sh The name of the shape.
  340.    * @return An Integer representing the shape.
  341.    */
  342.   private Integer getShape(String sh) {
  343.     if (sh.equalsIgnoreCase("box") || sh.equalsIgnoreCase("rectangle")) {
  344.       return new Integer(1);
  345.     }
  346.     else if (sh.equalsIgnoreCase("oval")) {
  347.       return new Integer(2);
  348.     }
  349.     else if (sh.equalsIgnoreCase("diamond")) {
  350.       return new Integer(3);
  351.     }
  352.     else {
  353.       return null;
  354.     }
  355.   }
  356.   
  357.   /**
  358.    * Converts the string representing the fill style int oa number 
  359.    * representing it.
  360.    *
  361.    * @param sty The name of the style.
  362.    * @return An Integer representing the shape.
  363.    */
  364.   private Integer getStyle(String sty) {
  365.     if (sty.equalsIgnoreCase("filled")) {
  366.       return new Integer(1);
  367.     }
  368.     else {
  369.       return null;
  370.     }
  371.   }
  372.   /**
  373.    * This will setup the syntax for the tokenizer so that it parses the 
  374.    * string properly.
  375.    *
  376.    */
  377.   private void setSyntax() {
  378.     m_st.resetSyntax();
  379.     m_st.eolIsSignificant(false);
  380.     m_st.slashStarComments(true);
  381.     m_st.slashSlashComments(true);
  382.     //System.out.println("slash");
  383.     m_st.whitespaceChars(0,' ');
  384.     m_st.wordChars(' '+1,'u00ff');
  385.     m_st.ordinaryChar('[');
  386.     m_st.ordinaryChar(']');
  387.     m_st.ordinaryChar('{');
  388.     m_st.ordinaryChar('}');
  389.     m_st.ordinaryChar('-');
  390.     m_st.ordinaryChar('>');
  391.     m_st.ordinaryChar('/');
  392.     m_st.ordinaryChar('*');
  393.     m_st.quoteChar('"');
  394.     m_st.whitespaceChars(';',';');
  395.     m_st.ordinaryChar('=');
  396.   }
  397.   /**
  398.    * This is the alternative syntax for the tokenizer.
  399.    */
  400.   private void alterSyntax() {
  401.     m_st.resetSyntax();
  402.     m_st.wordChars('u0000', 'u00ff');
  403.     m_st.slashStarComments(false);
  404.     m_st.slashSlashComments(false);
  405.     m_st.ordinaryChar('n');
  406.     m_st.ordinaryChar('r');
  407.   }
  408.   /**
  409.    * This will parse the next token out of the stream and check for certain 
  410.    * conditions.
  411.    *
  412.    * @param r The error string to print out if something goes wrong.
  413.    */
  414.   private void nextToken(String r) {
  415.     int t = 0;
  416.     try {
  417.       t = m_st.nextToken();
  418.     } catch(IOException e) {
  419.     }
  420.     
  421.     if (t == m_st.TT_EOF) {
  422.       System.out.println("eof , " + r);
  423.     }
  424.     else if (t == m_st.TT_NUMBER) {
  425.       System.out.println("got a number , " + r);
  426.     }
  427.   }
  428.   
  429.   /**
  430.    * Parses the top of the dotty stream that has the graph information.
  431.    *
  432.    */
  433.   private void graph() {
  434.     boolean flag = true;
  435.     String s;
  436.     //expect digraph
  437.     int t;
  438.     nextToken("expected 'digraph'");
  439.     
  440.     if (m_st.sval.equalsIgnoreCase("digraph")) {
  441.       m_digraph = true;
  442.     }
  443.     else {
  444.       System.out.println("expected 'digraph'");
  445.     }
  446.     
  447.     nextToken("expected a Graph Name");
  448.     if (m_st.sval != null) {
  449.       m_graphName = m_st.sval;
  450.     }
  451.     else {
  452.       System.out.println("expected a Graph Name");
  453.     }
  454.     
  455.     nextToken("expected '{'");
  456.     
  457.     if (m_st.ttype == '{') {
  458.       stmtList();
  459.     }
  460.     else {
  461.       System.out.println("expected '{'");
  462.     }
  463.   }
  464.   /**
  465.    * This is one of the states, this one is where new items can be defined 
  466.    * or the structure can end.
  467.    *
  468.    */
  469.   private void stmtList() {
  470.     boolean flag = true;
  471.     String s;
  472.     int t;
  473.     while(flag) {
  474.       nextToken("expects a STMT_LIST item or '}'");
  475.       if (m_st.ttype == '}') {
  476. flag = false;
  477.       }
  478.       else if (m_st.sval.equalsIgnoreCase("graph") ||
  479.        m_st.sval.equalsIgnoreCase("node") ||
  480.        m_st.sval.equalsIgnoreCase("edge")) {
  481. m_st.pushBack();
  482. attrStmt();
  483.       }
  484.       else if (m_st.sval != null) {
  485. nodeId(m_st.sval,0);
  486.       }
  487.       else {
  488. System.out.println("expects a STMT_LIST item or '}'");
  489.       }
  490.     }
  491.   }
  492.   /**
  493.    * This will deal specifically with a new object such as graph , node , edge.
  494.    *
  495.    */
  496.   private void attrStmt() {
  497.     
  498.     nextToken("expected 'graph' or 'node' or 'edge'");
  499.     
  500.     if (m_st.sval.equalsIgnoreCase("graph")) {
  501.       nextToken("expected a '['");
  502.       if (m_st.ttype == '[') {
  503. attrList(m_grObj);
  504.       }
  505.       else {
  506. System.out.println("expected a '['");
  507.       }
  508.     }
  509.     else if (m_st.sval.equalsIgnoreCase("node")) {
  510.       nextToken("expected a '['");
  511.       if (m_st.ttype == '[') {
  512. attrList(m_noObj);
  513.       }
  514.       else {
  515. System.out.println("expected a '['");
  516.       }
  517.     }
  518.     else if (m_st.sval.equalsIgnoreCase("edge")) {
  519.       nextToken("expected a '['");
  520.       if (m_st.ttype == '[') {
  521. attrList(m_edObj);
  522.       }
  523.       else {
  524. System.out.println("expected a '['");
  525.       }
  526.       
  527.     }
  528.     else {
  529.       System.out.println("expected 'graph' or 'node' or 'edge'"); 
  530.     }
  531.   }
  532.   /**
  533.    * Generates a new InfoObject with the specified name and either does 
  534.    * further processing if applicable
  535.    * Otherwise it is an edge and will deal with that.
  536.    *
  537.    * @param s The ID string.
  538.    * @param t Not sure!.
  539.    */
  540.   private void nodeId(String s,int t) {
  541.     
  542.     nextToken("error occurred in node_id");
  543.     if (m_st.ttype == '}') {
  544.       //creates a node if t is zero
  545.       if (t == 0) {
  546. m_nodes.addElement(new InfoObject(s));
  547.       }
  548.       m_st.pushBack();
  549.     }
  550.     else if (m_st.ttype == '-') {
  551.       nextToken("error occurred checking for an edge");
  552.       if (m_st.ttype == '>') {
  553. edgeStmt(s);
  554.       }
  555.       else {
  556. System.out.println("error occurred checking for an edge");
  557.       }
  558.     }
  559.     else if (m_st.ttype == '[') {
  560.       //creates a node if t is zero and sends it to attr
  561.       if (t == 0) {
  562. m_nodes.addElement(new InfoObject(s));
  563. attrList((InfoObject)m_nodes.lastElement());
  564.       }
  565.       else {
  566. attrList((InfoObject)m_edges.lastElement());
  567.       }
  568.     }
  569.     else if (m_st.sval != null) {
  570.       //creates a node if t is zero
  571.       if (t == 0) {
  572. m_nodes.addElement(new InfoObject(s));
  573.       }
  574.       m_st.pushBack();
  575.     }
  576.     else {
  577.       System.out.println("error occurred in node_id");
  578.     }
  579.   }
  580.   /**
  581.    * This will get the target of the edge.
  582.    *
  583.    * @param i The source of the edge.
  584.    */
  585.   private void edgeStmt(String i) {
  586.     nextToken("error getting target of edge");
  587.     
  588.     if (m_st.sval != null) {
  589.       m_edges.addElement(new InfoObject("an edge ,no id"));
  590.       ((InfoObject)m_edges.lastElement()).m_source = i;
  591.       ((InfoObject)m_edges.lastElement()).m_target = m_st.sval;
  592.       nodeId(m_st.sval,1);
  593.     }
  594.     else {
  595.       System.out.println("error getting target of edge");
  596.     }
  597.   }
  598.   /**
  599.    * This will parse all the items in the attrib list for an object.
  600.    *
  601.    * @param a The object that the attribs apply to.
  602.    */
  603.   private void attrList(InfoObject a) {
  604.     boolean flag = true;
  605.     
  606.     while (flag) {
  607.       nextToken("error in attr_list");
  608.       //System.out.println(st.sval);
  609.       if (m_st.ttype == ']') {
  610. flag = false;
  611.       }
  612.       else if (m_st.sval.equalsIgnoreCase("color")) {
  613. nextToken("error getting color");
  614. if (m_st.ttype == '=') {
  615.   nextToken("error getting color");
  616.   if (m_st.sval != null) {
  617.     a.m_color = m_st.sval;
  618.   }
  619.   else {
  620.     System.out.println("error getting color");
  621.   }
  622. }
  623. else {
  624.   System.out.println("error getting color");
  625. }
  626.       }
  627.       else if (m_st.sval.equalsIgnoreCase("fontcolor")) {
  628. nextToken("error getting font color");
  629. if (m_st.ttype == '=') {
  630.   nextToken("error getting font color");
  631.   if (m_st.sval != null) {
  632.     a.m_fontColor = m_st.sval;
  633.   }
  634.   else {
  635.     System.out.println("error getting font color");
  636.   }
  637. }
  638. else {
  639.   System.out.println("error getting font color");
  640. }
  641.       }
  642.       else if (m_st.sval.equalsIgnoreCase("fontsize")) {
  643. nextToken("error getting font size");
  644. if (m_st.ttype == '=') {
  645.   nextToken("error getting font size");
  646.   if (m_st.sval != null) {
  647.     a.m_fontSize = m_st.sval;
  648.   }
  649.   else {
  650.     System.out.println("error getting font size");
  651.   }
  652. }
  653. else {
  654.   System.out.println("error getting font size");
  655. }
  656.       }
  657.       else if (m_st.sval.equalsIgnoreCase("label")) {
  658. nextToken("error getting label");
  659. if (m_st.ttype == '=') {
  660.   nextToken("error getting label");
  661.   if (m_st.sval != null) {
  662.     a.m_label = m_st.sval;
  663.   }
  664.   else {
  665.     System.out.println("error getting label");
  666.   }
  667. }
  668. else {
  669.   System.out.println("error getting label");
  670. }
  671.       }
  672.       else if (m_st.sval.equalsIgnoreCase("shape")) {
  673. nextToken("error getting shape");
  674. if (m_st.ttype == '=') {
  675.   nextToken("error getting shape");
  676.   if (m_st.sval != null) {
  677.     a.m_shape = m_st.sval;
  678.   }
  679.   else {
  680.     System.out.println("error getting shape");
  681.   }
  682. }
  683. else {
  684.   System.out.println("error getting shape");
  685. }
  686.       }
  687.       else if (m_st.sval.equalsIgnoreCase("style")) {
  688. nextToken("error getting style");
  689. if (m_st.ttype == '=') {
  690.   nextToken("error getting style");
  691.   if (m_st.sval != null) {
  692.     a.m_style = m_st.sval;
  693.   }
  694.   else {
  695.     System.out.println("error getting style");
  696.   }
  697. }
  698. else {
  699.   System.out.println("error getting style");
  700. }
  701.       }
  702.       else if (m_st.sval.equalsIgnoreCase("data")) {
  703. nextToken("error getting data");
  704. if (m_st.ttype == '=') {
  705.   //data has a special data string that can have anything
  706.   //this is delimited by a single comma on an otherwise empty line
  707.   alterSyntax();
  708.   a.m_data = new String("");
  709.   
  710.   while (true) {
  711.     nextToken("error getting data");
  712.     if (m_st.sval != null && a.m_data 
  713. != null && m_st.sval.equals(",")) {
  714.       break;
  715.     }
  716.     else if (m_st.sval != null) {
  717.       a.m_data = a.m_data.concat(m_st.sval);
  718.     }
  719.     else if (m_st.ttype == 'r') {
  720.       a.m_data = a.m_data.concat("r");
  721.     }
  722.     else if (m_st.ttype == 'n') {
  723.       a.m_data = a.m_data.concat("n");
  724.     }
  725.     else {
  726.       System.out.println("error getting data");
  727.     }
  728.   }
  729.   setSyntax();
  730. }
  731. else {
  732.   System.out.println("error getting data");
  733. }
  734.       }
  735.     }
  736.   }
  737.   //special class for use in creating the tree
  738.   /**
  739.    * This is an internal class used to keep track of the info for the objects 
  740.    * before they are 
  741.    * actually created.
  742.    */
  743.   private class InfoObject {
  744.     /** The ID string for th object. */
  745.     public String m_id;
  746.     /** The color name for the object. */
  747.     public String m_color;
  748.     /** The font color for the object. not in use. */
  749.     public String m_fontColor;
  750.     /** The fontsize for the object. not in use. */
  751.     public String m_fontSize;
  752.     /** The label for the object. */
  753.     public String m_label;
  754.     /** The shape name of for the object. */
  755.     public String m_shape;
  756.     /** The backstyle name for the object. */
  757.     public String m_style;
  758.     /** The source ID of the object. */
  759.     public String m_source;
  760.     /** The target ID of the object. */
  761.     public String m_target;
  762.     /** The data for this object. */
  763.     public String m_data;
  764.     /**
  765.      * This will construct a new InfoObject with the specified ID string.
  766.      */
  767.     public InfoObject(String i) {
  768.       m_id = i;
  769.       m_color = null;
  770.       m_fontColor = null;
  771.       m_fontSize = null;
  772.       m_label = null;
  773.       m_shape = null;
  774.       m_style = null;
  775.       m_source = null;
  776.       m_target = null;
  777.       m_data = null;
  778.     }
  779.   }
  780. }