WanFactory - 2008-12-04

I've created a modification to allow XML to be passed in instead of read from the filesystem

here is the patch:

### Eclipse Workspace Patch 1.0
#P hypergraph
Index: source/hypergraph/graphApi/io/SAXReader.java
===================================================================
RCS file: /cvsroot/hypergraph/hypergraph/source/hypergraph/graphApi/io/SAXReader.java,v
retrieving revision 1.2
diff -u -r1.2 SAXReader.java
--- source/hypergraph/graphApi/io/SAXReader.java    23 Oct 2005 17:20:12 -0000    1.2
+++ source/hypergraph/graphApi/io/SAXReader.java    4 Dec 2008 21:49:44 -0000
@@ -21,6 +21,9 @@

package hypergraph.graphApi.io;

+import hypergraph.graphApi.Graph;
+import hypergraph.graphApi.GraphSystem;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
@@ -29,13 +32,13 @@
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

+import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;

-import hypergraph.graphApi.Graph;
-import hypergraph.graphApi.GraphSystem;
-
/**
  * @author Jens Kanschik
  *
@@ -55,6 +58,12 @@
         inputSource = new InputSource(filename);
         createLexicalHandler();
     }
+
+    public SAXReader(GraphSystem graphSystem, InputSource content) throws FileNotFoundException, IOException{
+        this.graphSystem = graphSystem;
+        inputSource = content;
+        createLexicalHandler();
+    }
     public SAXReader(GraphSystem graphSystem, URL url) throws IOException {
         this.graphSystem = graphSystem;
         inputSource = new InputSource(url.openStream());
@@ -83,12 +92,29 @@
         return graph;
     }
     public Graph parse() throws SAXException, IOException, ParserConfigurationException {
-        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+        return parse(null);
+    }
+    public Graph parse(final InputSource dtd) throws ParserConfigurationException, SAXException,
+            SAXNotRecognizedException, SAXNotSupportedException, IOException {
+        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
         SAXParser parser = parserFactory.newSAXParser();
         reader = parser.getXMLReader();
-        lexicalHandler.setSAXReader(this);
+        if (dtd != null) {
+            reader.setEntityResolver(new EntityResolver() {
+                @Override
+                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+                    if (systemId.indexOf("GraphXML.dtd") >= 0) {
+                        return dtd;
+                    } else {
+                        return null;
+                    }
+                }
+
+            });
+        }
+        lexicalHandler.setSAXReader(this);
         reader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
         reader.parse(inputSource);
         return getGraph();
-    }
+    }
}
Index: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
===================================================================
RCS file: source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
diff -N source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java
--- /dev/null    1 Jan 1970 00:00:00 -0000
+++ source/hypergraph/applications/hexplorer/DynamicXmlHExplorerApplet.java    1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,284 @@
+/*
+ *  Copyright (C) 2003  Jens Kanschik,
+ *     mail : jensKanschik@users.sourceforge.net
+ *
+ *  Part of <hypergraph>, an open source project at sourceforge.net
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+package hypergraph.applications.hexplorer;
+
+
+import hypergraph.graphApi.Graph;
+import hypergraph.graphApi.GraphSystem;
+import hypergraph.graphApi.GraphSystemFactory;
+import hypergraph.graphApi.Node;
+import hypergraph.graphApi.algorithms.GraphUtilities;
+import hypergraph.graphApi.io.GraphWriter;
+import hypergraph.graphApi.io.GraphXMLWriter;
+import hypergraph.graphApi.io.SAXReader;
+import hypergraph.visualnet.ArrowLineRenderer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.swing.JApplet;
+import javax.swing.JOptionPane;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * @author Jens Kanschik
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+public class DynamicXmlHExplorerApplet extends JApplet {
+    private static byte[] dtdbytes;
+    private static final String zipDtd = "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";
+    private static byte[] getDtdBytes() throws IOException {
+        return dtdbytes == null ? dtdbytes = StringZip.unzipBytes(zipDtd) :dtdbytes;
+    }
+
+    /** Stores the graph that the applet shows. */
+    private GraphPanel graphPanel;
+
+    public GraphPanel getGraphPanel() {
+        return graphPanel;
+    }
+    /**@inheritDoc */
+    public void init() {
+        GraphSystem graphSystem = null;
+        try {
+            graphSystem = GraphSystemFactory.createGraphSystem("hypergraph.graph.GraphSystemImpl", null);
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.exit(8);
+        }
+        Graph graph = null;
+        try {
+            InputSource source = createInput(StringZip
+                    .unzipBytes(getParameter("zipcontent")));
+            SAXReader reader = new SAXReader(graphSystem, source);
+            ContentHandlerFactory ch = new ContentHandlerFactory();
+            ch.setBaseUrl(getCodeBase());
+            reader.setContentHandlerFactory(ch);
+            graph = reader.parse(createInput(getDtdBytes()));
+        } catch (SAXException saxe) {
+            JOptionPane.showMessageDialog(null,
+                "Error while parsing dynamic xml. \n" +
+                "Exception : " + saxe + ". \n" +
+                "Start applet with default graph", "Parsing error", JOptionPane.ERROR_MESSAGE);
+            System.out.println("Exception : " + saxe);
+            saxe.getException().printStackTrace();
+            saxe.printStackTrace(System.out);
+        } catch (Exception e) {
+            JOptionPane.showMessageDialog(null,
+                "General error while reading dynamic xml. \n" +
+                "Exception : " + e + ". \n" +
+                "Start applet with default graph", "General error", JOptionPane.ERROR_MESSAGE);
+            System.out.println("Exception : " + e);
+            e.printStackTrace(System.out);
+        }
+
+        if (graph == null) {
+            graph = GraphUtilities.createTree(graphSystem, 2, 3);
+        }
+
+        graphPanel = new GraphPanel(graph, this);
+        String file = getParameter("properties");
+        URL url = null;
+        if (file != null)
+            try {
+                url = new URL(getCodeBase(), file);
+                graphPanel.loadProperties(url.openStream());
+            } catch (FileNotFoundException fnfe) {
+                JOptionPane.showMessageDialog(null,
+                    "Could not find propertyfile " + url.getFile() + ". \n" +
+                    "Start applet with default properties", "File not found", JOptionPane.ERROR_MESSAGE);
+            } catch (Exception e) {
+                JOptionPane.showMessageDialog(null,
+                    "General error while reading file " + url.getFile() + ". \n" +
+                    "Exception : " + e + ". \n" +
+                    "Start applet with default properties", "General error", JOptionPane.ERROR_MESSAGE);
+                System.out.println("Exception : " + e);
+                e.printStackTrace(System.out);
+            }
+
+        String center = getParameter("center");
+        if (center != null) {
+            Node n = (Node) graph.getElement(center);
+            if (n != null)
+                graphPanel.centerNode(n);
+        }
+        graphPanel.setLineRenderer(new ArrowLineRenderer());
+       
+        getContentPane().add(graphPanel);
+    }
+   
+    public String getGraphXML() {
+        try {
+            OutputStream os = new ByteArrayOutputStream();
+            GraphWriter graphWriter = new GraphXMLWriter(new OutputStreamWriter(os));
+            graphWriter.write(getGraphPanel().getGraph());
+            return os.toString();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            return ioe.toString();
+        }
+    }
+
+    private InputSource createInput(byte[] unzipBytes) {
+        return new InputSource(new ByteArrayInputStream(unzipBytes));
+    }
+}
+
+class StringZip {
+    // map 6-bit nibbles into base 64 characters
+    private static char[] map1 = new char[64];
+    static {
+        int i = 0;
+        for (char c = 'A'; c <= 'Z'; c++)
+            map1[i++] = c;
+        for (char c = 'a'; c <= 'z'; c++)
+            map1[i++] = c;
+        for (char c = '0'; c <= '9'; c++)
+            map1[i++] = c;
+        map1[i++] = '+';
+        map1[i++] = '/';
+    }
+
+    // Mapping table from Base64 characters to 6-bit nibbles.
+    private static byte[] map2 = new byte[128];
+    static {
+        for (int i = 0; i < map2.length; i++)
+            map2[i] = -1;
+        for (int i = 0; i < 64; i++)
+            map2[map1[i]] = (byte) i;
+    }
+
+    public static String zip(String input) throws IOException {
+        return encode64(zip(input.getBytes()));
+    }
+
+    public static String unzip(String input) throws IOException {
+        return new String(unzipBytes(input));
+    }
+
+    public static byte[] unzipBytes(String input) throws IOException {
+        return unzip(decode64(input));
+    }
+
+    private static byte[] unzip(byte[] zipped) throws IOException {
+        // TODO Auto-generated method stub
+        InputStream input = new GZIPInputStream(new ByteArrayInputStream(zipped));
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        copy(input, output);
+        input.close();
+        output.close();
+        return output.toByteArray();
+    }
+
+    private static byte[] zip(byte[] unzipped) throws IOException {
+        InputStream input = new ByteArrayInputStream(unzipped);
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        GZIPOutputStream zipout = new GZIPOutputStream(output);
+        copy(input, zipout);
+        input.close();
+        zipout.finish();
+        zipout.close();
+        return output.toByteArray();
+    }
+
+    private static void copy(InputStream input, OutputStream output) throws IOException {
+        byte[] buf = new byte[1024];
+        int len;
+        while ((len = input.read(buf)) > 0) {
+            output.write(buf, 0, len);
+        }
+        output.flush();
+    }
+
+    public static String encode64(byte[] in) {
+        int iLen = in.length;
+        int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
+        int oLen = ((iLen + 2) / 3) * 4; // output length including padding
+        char[] out = new char[oLen];
+        int ip = 0;
+        int op = 0;
+        while (ip < iLen) {
+            int i0 = in[ip++] & 0xff;
+            int i1 = ip < iLen ? in[ip++] & 0xff : 0;
+            int i2 = ip < iLen ? in[ip++] & 0xff : 0;
+            int o0 = i0 >>> 2;
+            int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
+            int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
+            int o3 = i2 & 0x3F;
+            out[op++] = map1[o0];
+            out[op++] = map1[o1];
+            out[op] = op < oDataLen ? map1[o2] : '=';
+            op++;
+            out[op] = op < oDataLen ? map1[o3] : '=';
+            op++;
+        }
+        return new String(out);
+    }
+
+    public static byte[] decode64(String input) {
+        char[] in = input.toCharArray();
+        int iLen = in.length;
+        if (iLen % 4 != 0)
+            throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");
+        while (iLen > 0 && in[iLen - 1] == '=')
+            iLen--;
+        int oLen = (iLen * 3) / 4;
+        byte[] out = new byte[oLen];
+        int ip = 0;
+        int op = 0;
+        while (ip < iLen) {
+            int i0 = in[ip++];
+            int i1 = in[ip++];
+            int i2 = ip < iLen ? in[ip++] : 'A';
+            int i3 = ip < iLen ? in[ip++] : 'A';
+            if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
+                throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
+            int b0 = map2[i0];
+            int b1 = map2[i1];
+            int b2 = map2[i2];
+            int b3 = map2[i3];
+            if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
+                throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
+            int o0 = (b0 << 2) | (b1 >>> 4);
+            int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
+            int o2 = ((b2 & 3) << 6) | b3;
+            out[op++] = (byte) o0;
+            if (op < oLen)
+                out[op++] = (byte) o1;
+            if (op < oLen)
+                out[op++] = (byte) o2;
+        }
+        return out;
+    }
+}