/* * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * BIFParser.java * Copyright (C) 2003 University of Waikato, Hamilton, New Zealand * */ package weka.gui.graphvisualizer; import java.io.InputStream; import java.io.FileWriter; import java.io.IOException; import java.io.StringReader; import java.util.StringTokenizer; import weka.core.FastVector; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.w3c.dom.Element; /** * This class parses an inputstream or a string in * XMLBIF ver. 0.3 format, and builds the datastructures * that are passed to it through the constructor. * * @author Ashraf M. Kibriya (amk14@cs.waikato.ac.nz) * @version $Revision: 1.7 $ - 24 Apr 2003 - Initial version (Ashraf M. Kibriya) */ public class BIFParser implements GraphConstants { /** These holds the nodes and edges of the graph */ protected FastVector m_nodes, m_edges; /** This holds the name of the graph (i.e. the name of network tag in XMLBIF * input) */ protected String graphName; /** This holds the string to be parsed */ protected String inString; /** This holds the InputStream to be parsed */ protected InputStream inStream; /** * Constructor (if our input is a String) * * @param input the string to be parsed (should not be null) * @param nodes vector containing GraphNode objects (should be empty) * @param edges vector containing GraphEdge objects (should be empty) */ public BIFParser(String input, FastVector nodes, FastVector edges) { m_nodes = nodes; m_edges = edges; inString = input; } /** * Constructor (if our input is an InputStream) * * @param instream the InputStream to be parsed (should not be null) * @param nodes vector containing GraphNode objects (should be empty) * @param edges vector containing GraphEdge objects (should be empty) */ public BIFParser(InputStream instream, FastVector nodes, FastVector edges) { m_nodes = nodes; m_edges = edges; inStream = instream; } /** * This method parses the string or the InputStream that we * passed in through the constructor and builds up the * m_nodes and m_edges vectors * @exception Exception if both the inString and inStream are * null, i.e. no input has been provided * @exception BIFFormatException if there is format of the * input is not correct. The format should conform to * XMLBIF version 0.3 * @exception NumberFormatException if there is an invalid * char in the probability table of a node. * @return returns the name of the graph */ public String parse() throws Exception { Document dc=null; javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance(); dbf.setIgnoringElementContentWhitespace(true); javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); if(inStream!=null) dc = db.parse(inStream); else if(inString!=null) dc = db.parse(new org.xml.sax.InputSource(new StringReader(inString))); else { throw new Exception("No input given"); } NodeList nl = dc.getElementsByTagName( "NETWORK" ); if(nl.getLength()==0) { throw new BIFFormatException( "NETWORK tag not found" ); } //take only the first network node NodeList templist = ((Element)nl.item(0)).getElementsByTagName( "NAME" ); graphName = templist.item(0).getFirstChild().getNodeValue(); //System.out.println("The name of the network is "+ //templist.item(0).getFirstChild().getNodeValue()); //Get all the variables nl = dc.getElementsByTagName("VARIABLE"); for(int i=0; i1) throw new BIFFormatException("More than one name tags found for "+ "variable no. "+(i+1)); String nodename = ((org.w3c.dom.Node)templist.item(0)).getFirstChild().getNodeValue(); GraphNode n = new GraphNode( nodename, nodename, GraphNode.NORMAL ); m_nodes.addElement(n); //getting nodes position templist = ((Element)nl.item(i)).getElementsByTagName("PROPERTY"); for(int j=0; j1) throw new BIFFormatException("More than one Probability Table for "+ n.ID); String probs = templist.item(0).getFirstChild().getNodeValue(); StringTokenizer tk = new StringTokenizer(probs, " \n\t"); if(parntOutcomes*n.outcomes.length > tk.countTokens()) throw new BIFFormatException("Probability Table for "+n.ID+ " contains more values than it should"); else if(parntOutcomes*n.outcomes.length < tk.countTokens()) throw new BIFFormatException("Probability Table for "+n.ID+ " contains less values than it should"); else { n.probs = new double[parntOutcomes][n.outcomes.length]; for(int r=0; r\n"); text.append("\n"); text.append("\n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append(" \n"); text.append("]>\n"); text.append("\n"); text.append("\n"); text.append("\n"); text.append("\n"); text.append("" + XMLNormalize(graphName) + "\n"); //Writing all the node names and their outcomes //If outcome is null(ie if the graph was loaded from DOT file) then //simply write TRUE for(int nodeidx=0; nodeidx\n"); text.append("\t" + XMLNormalize(n.ID) + "\n"); if(n.outcomes!=null) for(int outidx=0; outidx" + XMLNormalize(n.outcomes[outidx])+ "\n"); else text.append("\ttrue\n"); text.append("\tposition = ("+n.x+","+n.y+")\n"); text.append("\n"); } //Writing all the nodes definitions and their probability tables //If probability table is null then simply write 1 for all //the posible outcomes of the parents for (int nodeidx=0; nodeidx\n"); text.append("" + XMLNormalize(n.ID) + "\n"); int parntOutcomes = 1; if(n.prnts!=null) for(int pidx=0; pidx" + XMLNormalize(prnt.ID) + "\n"); if(prnt.outcomes!=null) parntOutcomes *= prnt.outcomes.length; } text.append("\n"); for(int i=0; i\n"); text.append("\n"); } text.append("\n"); text.append("\n"); outfile.write(text.toString()); outfile.close(); } catch(IOException ex) { ex.printStackTrace(); } } // writeXMLBIF /** XMLNormalize converts the five standard XML entities in a string * g.e. the string V&D's is returned as V&D's * @author Remco Bouckaert (rrb@xm.co.nz) * @param sStr string to normalize * @return normalized string */ private static String XMLNormalize(String sStr) { StringBuffer sStr2 = new StringBuffer(); for (int iStr = 0; iStr < sStr.length(); iStr++) { char c = sStr.charAt(iStr); switch (c) { case '&': sStr2.append("&"); break; case '\'': sStr2.append("'"); break; case '\"': sStr2.append("""); break; case '<': sStr2.append("<"); break; case '>': sStr2.append(">"); break; default: sStr2.append(c); } } return sStr2.toString(); } // XMLNormalize } // BIFParser