Package edu.ucla.sspace.graph.io

Source Code of edu.ucla.sspace.graph.io.GexfIO

/*
* Copyright 2011 David Jurgens
*
* This file is part of the S-Space package and is covered under the terms and
* conditions therein.
*
* The S-Space package is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation and distributed hereunder to you.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND NO REPRESENTATIONS OR WARRANTIES,
* EXPRESS OR IMPLIED ARE MADE.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, WE MAKE
* NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY
* PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR DOCUMENTATION
* WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER
* RIGHTS.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package edu.ucla.sspace.graph.io;

import edu.ucla.sspace.graph.DirectedEdge;
import edu.ucla.sspace.graph.DirectedGraph;
import edu.ucla.sspace.graph.DirectedMultigraph;
import edu.ucla.sspace.graph.DirectedTypedEdge;
import edu.ucla.sspace.graph.Edge;
import edu.ucla.sspace.graph.Multigraph;
import edu.ucla.sspace.graph.Graph;
import edu.ucla.sspace.graph.SimpleDirectedEdge;
import edu.ucla.sspace.graph.SimpleDirectedTypedEdge;
import edu.ucla.sspace.graph.SparseDirectedGraph;
import edu.ucla.sspace.graph.TypedEdge;
import edu.ucla.sspace.graph.WeightedEdge;
import edu.ucla.sspace.graph.WeightedGraph;

import edu.ucla.sspace.util.ColorGenerator;
import edu.ucla.sspace.util.Indexer;

import edu.ucla.sspace.util.primitive.IntIterator;

import java.awt.Color;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOError;
import java.io.IOException;

import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Element;
import org.w3c.dom.Document;
import javax.xml.parsers.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;


/**
* An implementation for writing {@link Graph} instances as <a
* href="http://gexf.net/format/">gexf</a>-formatted files, which are commonly
* used with the <a href="http://gephi.org">Gephi</a> graph program.
*/
public class GexfIO {

    /**
     * Writes the {@link Graph} to file in {@code gexf} format.
     */
    public void write(Graph<? extends Edge> g, File gexfFile)
            throws IOException {
        write(g, gexfFile, null);
    }

    /**
     * Writes the {@link Graph} to file in {@code gexf} format.
     */
    public void write(Graph<? extends Edge> g,
                      File gexfFile, Indexer<String> vertexLabels)
            throws IOException {

        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = dbfac.newDocumentBuilder();
        } catch (ParserConfigurationException pce) {
            throw new IOError(new IOException(pce));
        }
        Document doc = docBuilder.newDocument();

        Element root = doc.createElement("gexf");
        root.setAttribute("xmlns","http://www.gexf.net/1.2draft");
        root.setAttribute("xmlns:viz", "http://www.gexf.net/1.2draft/viz");
        root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        root.setAttribute("version","1.2");
        root.setAttribute("xsi:schemaLocation","http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd");
        doc.appendChild(root);

        Element graph = doc.createElement("graph");
        graph.setAttribute("defaultedgetype","undirected");
        root.appendChild(graph);

        Element nodes = doc.createElement("nodes");
        graph.appendChild(nodes);
        Element edges = doc.createElement("edges");
        graph.appendChild(edges);

        IntIterator vIter = g.vertices().iterator();
        while (vIter.hasNext()) {
            int vertex = vIter.next();
            Element node = doc.createElement("node");
            String vLabel = (vertexLabels == null)
                ? String.valueOf(vertex)
                : vertexLabels.lookup(vertex);
            if (vLabel == null)
                vLabel = String.valueOf(vertex);
            node.setAttribute("id", vLabel);
            node.setAttribute("label", vLabel);
            nodes.appendChild(node);
        }

        int edgeId = 0;
        for (Edge e : g.edges()) {
            Element edge = doc.createElement("edge");
            edges.appendChild(edge);
            edge.setAttribute("id", "" + (edgeId++));

            String sourceLabel = (vertexLabels == null)
                ? String.valueOf(e.from())
                : vertexLabels.lookup(e.from());
            if (sourceLabel == null)
                sourceLabel = String.valueOf(e.from());

            String targetLabel = (vertexLabels == null)
                ? String.valueOf(e.to())
                : vertexLabels.lookup(e.to());
            if (targetLabel == null)
                targetLabel = String.valueOf(e.to());

            edge.setAttribute("source", sourceLabel);
            edge.setAttribute("target", targetLabel);
        }

        // Set up a transformer
        try {
            TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            trans.setOutputProperty(OutputKeys.INDENT, "yes");
            trans.setOutputProperty(
                "{http://xml.apache.org/xslt}indent-amount", "2");
       
            // Create string from xml tree
            BufferedOutputStream bos =
                new BufferedOutputStream(new FileOutputStream(gexfFile));
            StreamResult result = new StreamResult(bos);
            DOMSource source = new DOMSource(doc);
            trans.transform(source, result);
            bos.close();        
        } catch (TransformerException te) {
            throw new IOError(new IOException(te));
        }
    }

    /**
     * Writes the provided multigraph to the specified {@code gexf} file with
     * all edge colors appearing the same.
     *
     * @param f the file where the {@code gexf} graph will be written.  Any existing file
     *        contents will be overwritten
         */
    public <T,E extends TypedEdge<T>> void write(
                        Multigraph<T,E> g, File f) throws IOException {
        write(g, f, null, false, null, false);
    }

    /**
     * Writes the provided multigraph to the specified {@code gexf} file, using
     * {@code edgeColors} as a guide for how to display parallel edges of
     * different types.
     *
     * @param f the file where the {@code gexf} graph will be written.  Any
     *        existing file contents will be overwritten
     * @param edgeColor a mapping from an edge type to a color.  Types that do
     *        not have colors will be randomly assigned one and the {@code
     *        edgeColors} map will be updated appropriately.
     */
    public <T,E extends TypedEdge<T>> void write(
                        Multigraph<T,E> g, File f, Map<T,Color> edgeColors)
                        throws IOException {
        write(g, f, edgeColors, true, null, false);
    }

    /**
     * Writes the provided multigraph to the specified {@code gexf} file, using
     * {@code vertexLabels} to name the vertices.
     *
     * @param f the file where the {@code gexf} graph will be written.  Any
     *        existing file contents will be overwritten
     * @param vertexLabels a mapping from vertex value to a string name for the
     *        vertex
     */
    public <T,E extends TypedEdge<T>> void write(
                        Multigraph<T,E> g, File f,
                        Indexer<String> vertexLabels)
                        throws IOException {
        write(g, f, null, false, vertexLabels, true);
    }

    /**
     * Writes the provided multigraph to the specified {@code gexf} file, using
     * {@code edgeColors} as a guide for how to display parallel edges of
     * different types, and {@code vertexLabels} to name the vertices.
     *
     * @param f the file where the {@code gexf} graph will be written.  Any
     *        existing file contents will be overwritten
     * @param edgeColor a mapping from an edge type to a color.  Types that do
     *        not have colors will be randomly assigned one and the {@code
     *        edgeColors} map will be updated appropriately.
     * @param vertexLabels a mapping from vertex value to a string name for the
     *        vertex
     */
    public <T,E extends TypedEdge<T>> void write(
                        Multigraph<T,E> g, File f, Map<T,Color> edgeColors,
                        Indexer<String> vertexLabels)
                        throws IOException {
        write(g, f, edgeColors, true, vertexLabels, true);
    }

    /**
     * Writes the provided multigraph to the specified {@code gexf} file,
     * optionally coloring the edges if specified.
     */
    private <T,E extends TypedEdge<T>> void write(
                         Multigraph<T,E> g, File f, Map<T,Color> edgeColors,
                         boolean useColors, Indexer<String> vertexLabels,
                         boolean useLabels) throws IOException {

        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = dbfac.newDocumentBuilder();
        } catch (ParserConfigurationException pce) {
            throw new IOError(new IOException(pce));
        }
        Document doc = docBuilder.newDocument();

        Element root = doc.createElement("gexf");
        root.setAttribute("xmlns","http://www.gexf.net/1.2draft");
        root.setAttribute("xmlns:viz", "http://www.gexf.net/1.2draft/viz");
        root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        root.setAttribute("version","1.2");
        root.setAttribute("xsi:schemaLocation","http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd");
        doc.appendChild(root);

        Element graph = doc.createElement("graph");
        graph.setAttribute("defaultedgetype","undirected");
        root.appendChild(graph);

        Element nodes = doc.createElement("nodes");
        graph.appendChild(nodes);
        Element edges = doc.createElement("edges");
        graph.appendChild(edges);

        IntIterator vIter = g.vertices().iterator();
        while (vIter.hasNext()) {
            int vertex = vIter.next();
            Element node = doc.createElement("node");
            node.setAttribute("id", String.valueOf(vertex));
            if (useLabels)
                node.setAttribute("label", vertexLabels.lookup(vertex));
            else
                node.setAttribute("label", String.valueOf(vertex));
            nodes.appendChild(node);
        }

        ColorGenerator cg = null;
        if (useColors)
            cg = new ColorGenerator();

        int edgeId = 0;
        for (E e : g.edges()) {
            Element edge = doc.createElement("edge");
            edges.appendChild(edge);
            edge.setAttribute("id", "" + (edgeId++));
            edge.setAttribute("source", String.valueOf(e.from()));
            edge.setAttribute("target", String.valueOf(e.to()));
            edge.setAttribute("label", String.valueOf(e.edgeType()));
            if (useColors) {
                Element cEdge = doc.createElement("viz:color");
                edge.appendChild(cEdge);
                Color c = edgeColors.get(e.edgeType());
                if (c == null) {
                    c = cg.next();
                    edgeColors.put(e.edgeType(), c);
                }
                cEdge.setAttribute("r", String.valueOf(c.getRed()));
                cEdge.setAttribute("g", String.valueOf(c.getGreen()));
                cEdge.setAttribute("b", String.valueOf(c.getBlue()));
            }
        }

        // Set up a transformer
        try {
            TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            trans.setOutputProperty(OutputKeys.INDENT, "yes");
            trans.setOutputProperty(
                "{http://xml.apache.org/xslt}indent-amount", "2");
       
            // Create string from xml tree
            BufferedOutputStream bos =
                new BufferedOutputStream(new FileOutputStream(f));
            StreamResult result = new StreamResult(bos);
            DOMSource source = new DOMSource(doc);
            trans.transform(source, result);
            bos.close();        
        } catch (TransformerException te) {
            throw new IOError(new IOException(te));
        }
    }

    /**
     * Writes the {@link WeightedGraph} to file in {@code gexf} format.
     */
    public void write(WeightedGraph<? extends WeightedEdge> g, File gexfFile)
            throws IOException {
        write(g, gexfFile, null);
    }

    /**
     * Writes the {@link WeightedGraph} to file in {@code gexf} format.
     */
    public void write(WeightedGraph<? extends WeightedEdge> g,
                      File gexfFile, Indexer<String> vertexLabels)
            throws IOException {

        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = dbfac.newDocumentBuilder();
        } catch (ParserConfigurationException pce) {
            throw new IOError(new IOException(pce));
        }
        Document doc = docBuilder.newDocument();

        Element root = doc.createElement("gexf");
        root.setAttribute("xmlns","http://www.gexf.net/1.2draft");
        root.setAttribute("xmlns:viz", "http://www.gexf.net/1.2draft/viz");
        root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        root.setAttribute("version","1.2");
        root.setAttribute("xsi:schemaLocation","http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd");
        doc.appendChild(root);

        Element graph = doc.createElement("graph");
        graph.setAttribute("defaultedgetype","undirected");
        root.appendChild(graph);

        Element nodes = doc.createElement("nodes");
        graph.appendChild(nodes);
        Element edges = doc.createElement("edges");
        graph.appendChild(edges);

        IntIterator vIter = g.vertices().iterator();
        while (vIter.hasNext()) {
            int vertex = vIter.next();
            Element node = doc.createElement("node");
            String vLabel = (vertexLabels == null)
                ? String.valueOf(vertex)
                : vertexLabels.lookup(vertex);
            if (vLabel == null)
                vLabel = String.valueOf(vertex);
            node.setAttribute("id", vLabel);
            node.setAttribute("label", vLabel);
            nodes.appendChild(node);
        }

        int edgeId = 0;
        for (WeightedEdge e : g.edges()) {
            Element edge = doc.createElement("edge");
            edges.appendChild(edge);
            edge.setAttribute("id", "" + (edgeId++));

            String sourceLabel = (vertexLabels == null)
                ? String.valueOf(e.from())
                : vertexLabels.lookup(e.from());
            if (sourceLabel == null)
                sourceLabel = String.valueOf(e.from());

            String targetLabel = (vertexLabels == null)
                ? String.valueOf(e.to())
                : vertexLabels.lookup(e.to());
            if (targetLabel == null)
                targetLabel = String.valueOf(e.to());

            edge.setAttribute("source", sourceLabel);
            edge.setAttribute("target", targetLabel);
            edge.setAttribute("weight", String.valueOf(e.weight()));
        }

        // Set up a transformer
        try {
            TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            trans.setOutputProperty(OutputKeys.INDENT, "yes");
            trans.setOutputProperty(
                "{http://xml.apache.org/xslt}indent-amount", "2");
       
            // Create string from xml tree
            BufferedOutputStream bos =
                new BufferedOutputStream(new FileOutputStream(gexfFile));
            StreamResult result = new StreamResult(bos);
            DOMSource source = new DOMSource(doc);
            trans.transform(source, result);
            bos.close();        
        } catch (TransformerException te) {
            throw new IOError(new IOException(te));
        }
    }

}
TOP

Related Classes of edu.ucla.sspace.graph.io.GexfIO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.