Package org.gephi.io.exporter.plugin

Source Code of org.gephi.io.exporter.plugin.ExporterGraphML

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>,
Sebastien Heymann <sebastien.heymann@gephi.org>
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.io.exporter.plugin;

import java.awt.Color;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.data.attributes.api.AttributeOrigin;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.dynamic.DynamicUtilities;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.EdgeIterable;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.NodeData;
import org.gephi.io.exporter.api.FileType;
import org.gephi.io.exporter.spi.GraphExporter;
import org.gephi.io.exporter.spi.CharacterExporter;
import org.gephi.project.api.Workspace;
import org.gephi.utils.longtask.spi.LongTask;
import org.gephi.utils.progress.Progress;
import org.gephi.utils.progress.ProgressTicket;
import org.openide.util.NbBundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
*
* @author Sebastien Heymann
* @author Mathieu Bastian
*/
public class ExporterGraphML implements GraphExporter, CharacterExporter, LongTask {

    private boolean cancel = false;
    private ProgressTicket progressTicket;
    private Workspace workspace;
    private Writer writer;
    private boolean exportVisible;
    private GraphModel graphModel;
    private AttributeModel attributeModel;
    //Settings
    private boolean normalize = false;
    private boolean exportColors = true;
    private boolean exportPosition = true;
    private boolean exportSize = true;
    private boolean exportAttributes = true;
    private boolean exportHierarchy = false;
    //Settings Helper
    private float minSize;
    private float maxSize;
    private float minX;
    private float maxX;
    private float minY;
    private float maxY;
    private float minZ;
    private float maxZ;
    //Dynamic
    private TimeInterval visibleInterval;

    public boolean execute() {
        attributeModel = workspace.getLookup().lookup(AttributeModel.class);
        graphModel = workspace.getLookup().lookup(GraphModel.class);
        HierarchicalGraph graph = null;
        if (exportVisible) {
            graph = graphModel.getHierarchicalGraphVisible();
        } else {
            graph = graphModel.getHierarchicalGraph();
        }
        DynamicModel dynamicModel = workspace.getLookup().lookup(DynamicModel.class);
        visibleInterval = dynamicModel != null && exportVisible ? dynamicModel.getVisibleInterval() : new TimeInterval();
        try {
            exportData(createDocument(), graph, attributeModel);
        } catch (Exception e) {
            graph.readUnlockAll();
            throw new RuntimeException(e);
        }

        return !cancel;
    }

    public Document createDocument() throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        final Document document = documentBuilder.newDocument();
        document.setXmlVersion("1.0");
        document.setXmlStandalone(true);
        return document;
    }

    private void transform(Document document) throws TransformerConfigurationException, TransformerException {
        Source source = new DOMSource(document);
        Result result = new StreamResult(writer);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.transform(source, result);
    }

    /*
    public Schema getSchema() {
    try {
    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    return sf.newSchema(new URL("http://www.gexf.net/1.1draft/gexf.xsd"));
    } catch (MalformedURLException ex) {
    Exceptions.printStackTrace(ex);
    } catch (SAXException ex) {
    Exceptions.printStackTrace(ex);
    }
    return null;
    }
     */
    public boolean exportData(Document document, HierarchicalGraph graph, AttributeModel model) throws Exception {
        Progress.start(progressTicket);

        graph.readLock();

        //Options
        calculateMinMax(graph);

        //Calculate progress units count
        int max;
        if (graphModel.isHierarchical()) {
            HierarchicalGraph hgraph = graphModel.getHierarchicalGraph();
            max = hgraph.getNodeCount() + hgraph.getEdgeCount();
        } else {
            max = graph.getNodeCount() + graph.getEdgeCount();
        }
        Progress.switchToDeterminate(progressTicket, max);

        Element root = document.createElementNS("http://graphml.graphdrawing.org/xmlns", "graphml");
        document.appendChild(root);

        createKeys(document, root);

        Element graphE = createGraph(document, graph);
        root.appendChild(graphE);

        graph.readUnlockAll();

        if (!cancel) {
            transform(document);
        }

        Progress.finish(progressTicket);
        return !cancel;
    }

    private void createKeys(Document document, Element root) {
        Element nodeLabelKeyE = document.createElement("key");
        nodeLabelKeyE.setAttribute("id", "label");
        nodeLabelKeyE.setAttribute("attr.name", "label");
        nodeLabelKeyE.setAttribute("attr.type", "string");
        nodeLabelKeyE.setAttribute("for", "node");
        root.appendChild(nodeLabelKeyE);

        Element edgeLabelKeyE = document.createElement("key");
        edgeLabelKeyE.setAttribute("id", "edgelabel");
        edgeLabelKeyE.setAttribute("attr.name", "Edge Label");
        edgeLabelKeyE.setAttribute("attr.type", "string");
        edgeLabelKeyE.setAttribute("for", "edge");
        root.appendChild(edgeLabelKeyE);

        Element weightKeyE = document.createElement("key");
        weightKeyE.setAttribute("id", "weight");
        weightKeyE.setAttribute("attr.name", "weight");
        weightKeyE.setAttribute("attr.type", "double");
        weightKeyE.setAttribute("for", "edge");
        root.appendChild(weightKeyE);

        Element edgeIdKeyE = document.createElement("key");
        edgeIdKeyE.setAttribute("id", "edgeid");
        edgeIdKeyE.setAttribute("attr.name", "Edge Id");
        edgeIdKeyE.setAttribute("attr.type", "string");
        edgeIdKeyE.setAttribute("for", "edge");
        root.appendChild(edgeIdKeyE);

        if (exportColors) {
            Element colorRKeyE = document.createElement("key");
            colorRKeyE.setAttribute("id", "r");
            colorRKeyE.setAttribute("attr.name", "r");
            colorRKeyE.setAttribute("attr.type", "int");
            colorRKeyE.setAttribute("for", "node");
            root.appendChild(colorRKeyE);

            Element colorGKeyE = document.createElement("key");
            colorGKeyE.setAttribute("id", "g");
            colorGKeyE.setAttribute("attr.name", "g");
            colorGKeyE.setAttribute("attr.type", "int");
            colorGKeyE.setAttribute("for", "node");
            root.appendChild(colorGKeyE);

            Element colorBKeyE = document.createElement("key");
            colorBKeyE.setAttribute("id", "b");
            colorBKeyE.setAttribute("attr.name", "b");
            colorBKeyE.setAttribute("attr.type", "int");
            colorBKeyE.setAttribute("for", "node");
            root.appendChild(colorBKeyE);
        }

        if (exportPosition) {
            Element positionKeyE = document.createElement("key");
            positionKeyE.setAttribute("id", "x");
            positionKeyE.setAttribute("attr.name", "x");
            positionKeyE.setAttribute("attr.type", "float");
            positionKeyE.setAttribute("for", "node");
            root.appendChild(positionKeyE);

            Element positionKey2E = document.createElement("key");
            positionKey2E.setAttribute("id", "y");
            positionKey2E.setAttribute("attr.name", "y");
            positionKey2E.setAttribute("attr.type", "float");
            positionKey2E.setAttribute("for", "node");
            root.appendChild(positionKey2E);
           
            if (minZ != 0f || maxZ != 0f) {
                Element positionKey3E = document.createElement("key");
                positionKey3E.setAttribute("id", "z");
                positionKey3E.setAttribute("attr.name", "z");
                positionKey3E.setAttribute("attr.type", "float");
                positionKey3E.setAttribute("for", "node");
                root.appendChild(positionKey3E);
            }
        }

        if (exportSize) {
            Element sizeKeyE = document.createElement("key");
            sizeKeyE.setAttribute("id", "size");
            sizeKeyE.setAttribute("attr.name", "size");
            sizeKeyE.setAttribute("attr.type", "float");
            sizeKeyE.setAttribute("for", "node");
            root.appendChild(sizeKeyE);
        }

        //Attributes
        if (attributeModel != null && exportAttributes) {
            //Node attributes
            for (AttributeColumn column : attributeModel.getNodeTable().getColumns()) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    Element attributeE = createAttribute(document, column);
                    attributeE.setAttribute("for", "node");
                    root.appendChild(attributeE);
                }
            }

            for (AttributeColumn column : attributeModel.getEdgeTable().getColumns()) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    //Data or computed
                    Element attributeE = createAttribute(document, column);
                    attributeE.setAttribute("for", "edge");
                    root.appendChild(attributeE);
                }
            }
        }
    }

    private Element createGraph(Document document, Graph graph) throws Exception {
        Element graphE = document.createElement("graph");

        if (graphModel.isDirected()) {
            graphE.setAttribute("edgedefault", "directed");
        } else {
            graphE.setAttribute("edgedefault", "undirected"); // defaultValue
        }

        //Nodes
        createNodes(document, graphE, graph, null);

        //Edges
        createEdges(document, graphE, graph);

        return graphE;
    }

    private Element createAttribute(Document document, AttributeColumn column) {
        Element attributeE = document.createElement("key");
        attributeE.setAttribute("id", column.getId());
        attributeE.setAttribute("attr.name", column.getTitle());
        switch (column.getType()) {
            case INT:
                attributeE.setAttribute("attr.type", "int");
                break;
            default:
                attributeE.setAttribute("attr.type", column.getType().getTypeString().toLowerCase());
                break;
        }
        if (column.getDefaultValue() != null) {
            Element defaultE = document.createElement("default");
            Text defaultTextE = document.createTextNode(column.getDefaultValue().toString());
            defaultE.appendChild(defaultTextE);
        }
        return attributeE;
    }

    private Element createNodeAttvalue(Document document, AttributeColumn column, Node n) throws Exception {
        int index = column.getIndex();
        if (n.getNodeData().getAttributes().getValue(index) != null) {
            Object val = n.getNodeData().getAttributes().getValue(index);
            val = DynamicUtilities.getDynamicValue(val, visibleInterval.getLow(), visibleInterval.getHigh());
            String value = val.toString();
            String id = column.getId();

            Element attvalueE = document.createElement("data");
            attvalueE.setAttribute("key", id);
            attvalueE.setTextContent(value);
            return attvalueE;
        }
        return null;
    }

    private Element createEdgeAttvalue(Document document, AttributeColumn column, Edge e) throws Exception {
        int index = column.getIndex();
        if (e.getEdgeData().getAttributes().getValue(index) != null) {
            Object val = e.getEdgeData().getAttributes().getValue(index);
            val = DynamicUtilities.getDynamicValue(val, visibleInterval.getLow(), visibleInterval.getHigh());
            String value = val.toString();
            String id = column.getId();

            Element attvalueE = document.createElement("data");
            attvalueE.setAttribute("key", id);
            attvalueE.setTextContent(value);
            return attvalueE;
        }
        return null;
    }

    private void createNodes(Document document, Element parentE, Graph graph, Node nodeParent) throws Exception {

        if (nodeParent != null) {
            Element graphE = document.createElement("graph");

            if (graphModel.isDirected()) {
                graphE.setAttribute("edgedefault", "directed");
            } else {
                graphE.setAttribute("edgedefault", "undirected"); // defaultValue
            }
            // we are inside the tree
            HierarchicalGraph hgraph = graphModel.getHierarchicalGraph();
            for (Node n : hgraph.getChildren(nodeParent)) {
                Element childE = createNode(document, graph, n);
                graphE.appendChild(childE);
            }
            parentE.appendChild(graphE);
        } else if (exportHierarchy && graphModel.isHierarchical()) {
            // we are on the top of the tree
            HierarchicalGraph hgraph = graphModel.getHierarchicalGraph();
            for (Node n : hgraph.getTopNodes()) {
                Element nodeE = createNode(document, hgraph, n);
                parentE.appendChild(nodeE);
            }
        } else {
            // there is no tree
            for (Node n : graph.getNodes()) {
                if (cancel) {
                    break;
                }
                Element nodeE = createNode(document, graph, n);
                parentE.appendChild(nodeE);
            }
        }
    }

    private Element createNode(Document document, Graph graph, Node n) throws Exception {
        Element nodeE = document.createElement("node");
        nodeE.setAttribute("id", n.getNodeData().getId());

        //Label
        if (n.getNodeData().getLabel() != null && !n.getNodeData().getLabel().isEmpty()) {
            Element labelE = createNodeLabel(document, n);
            nodeE.appendChild(labelE);
        }

        //Attribute values
        if (attributeModel != null && exportAttributes) {
            for (AttributeColumn column : attributeModel.getNodeTable().getColumns()) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    //Data or computed
                    Element attvalueE = createNodeAttvalue(document, column, n);
                    if (attvalueE != null) {
                        nodeE.appendChild(attvalueE);
                    }
                }
            }
        }

        //Viz
        if (exportSize) {
            Element sizeE = createNodeSize(document, n);
            nodeE.appendChild(sizeE);
        }
        if (exportColors) {
            Element colorE = createNodeColorR(document, n);
            nodeE.appendChild(colorE);

            colorE = createNodeColorG(document, n);
            nodeE.appendChild(colorE);

            colorE = createNodeColorB(document, n);
            nodeE.appendChild(colorE);
        }
        if (exportPosition) {
            Element positionXE = createNodePositionX(document, n);
            nodeE.appendChild(positionXE);
            Element positionYE = createNodePositionY(document, n);
            nodeE.appendChild(positionYE);
            if (minZ != 0f || maxZ != 0f) {
                Element positionZE = createNodePositionZ(document, n);
                nodeE.appendChild(positionZE);
            }
        }

        //Hierarchy
        if (exportHierarchy && graphModel.isHierarchical()) {
            HierarchicalGraph hgraph = graphModel.getHierarchicalGraph();
            int childCount = hgraph.getChildrenCount(n);
            if (childCount != 0) {
                createNodes(document, nodeE, graph, n);
            }
        }
        Progress.progress(progressTicket);

        return nodeE;
    }

    private void createEdges(Document document, Element edgesE, Graph graph) throws Exception {

        EdgeIterable it;
        HierarchicalGraph hgraph = graphModel.getHierarchicalGraph();
        if (exportHierarchy && graphModel.isHierarchical()) {
            it = hgraph.getEdgesTree();
        } else {
            it = hgraph.getEdgesAndMetaEdges();
        }
        for (Edge e : it.toArray()) {
            if (cancel) {
                break;
            }
            Element edgeE = createEdge(document, e);
            edgesE.appendChild(edgeE);
        }
    }

    private Element createEdge(Document document, Edge e) throws Exception {
        Element edgeE = document.createElement("edge");

        edgeE.setAttribute("source", e.getSource().getNodeData().getId());
        edgeE.setAttribute("target", e.getTarget().getNodeData().getId());

        if (e.getEdgeData().getId() != null && !e.getEdgeData().getId().isEmpty() && !String.valueOf(e.getId()).equals(e.getEdgeData().getId())) {
            Element idE = createEdgeId(document, e);
            edgeE.appendChild(idE);
        }

        //Label
        if (e.getEdgeData().getLabel() != null && !e.getEdgeData().getLabel().isEmpty()) {
            Element labelE = createEdgeLabel(document, e);
            edgeE.appendChild(labelE);
        }

        Element weightE = createEdgeWeight(document, e);
        edgeE.appendChild(weightE);

        if (e.isDirected() && !graphModel.isDirected()) {
            edgeE.setAttribute("type", "directed");
        } else if (!e.isDirected() && graphModel.isDirected()) {
            edgeE.setAttribute("type", "undirected");
        }

        //Attribute values
        if (attributeModel != null) {
            for (AttributeColumn column : attributeModel.getEdgeTable().getColumns()) {
                if (!column.getOrigin().equals(AttributeOrigin.PROPERTY)) {
                    //Data or computed
                    Element attvalueE = createEdgeAttvalue(document, column, e);
                    if (attvalueE != null) {
                        edgeE.appendChild(attvalueE);
                    }
                }
            }
        }
        Progress.progress(progressTicket);

        return edgeE;
    }

    private Element createNodeSize(Document document, Node n) throws Exception {
        Element sizeE = document.createElement("data");
        float size = n.getNodeData().getSize();
        if (normalize) {
            size = (size - minSize) / (maxSize - minSize);
        }
        sizeE.setAttribute("key", "size");
        sizeE.setTextContent("" + size);

        return sizeE;
    }

    private Element createNodeColorR(Document document, Node n) throws Exception {
        int r = Math.round(n.getNodeData().r() * 255f);
        Element colorE = document.createElement("data");
        colorE.setAttribute("key", "r");
        colorE.setTextContent("" + r);
        return colorE;
    }

    private Element createNodeColorG(Document document, Node n) throws Exception {
        int g = Math.round(n.getNodeData().g() * 255f);
        Element colorE = document.createElement("data");
        colorE.setAttribute("key", "g");
        colorE.setTextContent("" + g);
        return colorE;
    }

    private Element createNodeColorB(Document document, Node n) throws Exception {
        int b = Math.round(n.getNodeData().b() * 255f);
        Element colorE = document.createElement("data");
        colorE.setAttribute("key", "b");
        colorE.setTextContent("" + b);
        return colorE;
    }

    private Element createNodePositionX(Document document, Node n) throws Exception {
        Element positionXE = document.createElement("data");
        float x = n.getNodeData().x();
        if (normalize && x != 0.0) {
            x = (x - minX) / (maxX - minX);
        }
        positionXE.setAttribute("key", "x");
        positionXE.setTextContent("" + x);
        return positionXE;
    }

    private Element createNodePositionY(Document document, Node n) throws Exception {
        Element positionYE = document.createElement("data");
        float y = n.getNodeData().y();
        if (normalize && y != 0.0) {
            y = (y - minY) / (maxY - minY);
        }
        positionYE.setAttribute("key", "y");
        positionYE.setTextContent("" + y);

        return positionYE;
    }

    private Element createNodePositionZ(Document document, Node n) throws Exception {
        Element positionZE = document.createElement("data");
        float z = n.getNodeData().z();
        if (normalize && z != 0.0) {
            z = (z - minZ) / (maxZ - minZ);
        }
        positionZE.setAttribute("key", "z");
        positionZE.setTextContent("" + z);

        return positionZE;
    }

    private Element createNodeLabel(Document document, Node n) throws Exception {
        Element labelE = document.createElement("data");
        labelE.setAttribute("key", "label");
        labelE.setTextContent(n.getNodeData().getLabel());

        return labelE;
    }

    private Element createEdgeId(Document document, Edge e) throws Exception {
        Element idE = document.createElement("data");
        idE.setAttribute("key", "edgeid");
        idE.setTextContent(e.getEdgeData().getId());

        return idE;
    }

    private Element createEdgeWeight(Document document, Edge e) throws Exception {
        Element weightE = document.createElement("data");
        weightE.setAttribute("key", "weight");
        weightE.setTextContent(Float.toString(e.getWeight(visibleInterval.getLow(), visibleInterval.getHigh())));

        return weightE;
    }

    private Element createEdgeLabel(Document document, Edge e) throws Exception {
        Element labelE = document.createElement("data");
        labelE.setAttribute("key", "edgelabel");
        labelE.setTextContent(e.getEdgeData().getLabel());

        return labelE;
    }

    private void calculateMinMax(Graph graph) {
        minX = Float.POSITIVE_INFINITY;
        maxX = Float.NEGATIVE_INFINITY;
        minY = Float.POSITIVE_INFINITY;
        maxY = Float.NEGATIVE_INFINITY;
        minZ = Float.POSITIVE_INFINITY;
        maxZ = Float.NEGATIVE_INFINITY;
        minSize = Float.POSITIVE_INFINITY;
        maxSize = Float.NEGATIVE_INFINITY;

        for (Node node : graph.getNodes()) {
            NodeData nodeData = node.getNodeData();
            minX = Math.min(minX, nodeData.x());
            maxX = Math.max(maxX, nodeData.x());
            minY = Math.min(minY, nodeData.y());
            maxY = Math.max(maxY, nodeData.y());
            minZ = Math.min(minZ, nodeData.z());
            maxZ = Math.max(maxZ, nodeData.z());
            minSize = Math.min(minSize, nodeData.getSize());
            maxSize = Math.max(maxSize, nodeData.getSize());
        }
    }

    public boolean cancel() {
        cancel = true;
        return true;
    }

    public void setProgressTicket(ProgressTicket progressTicket) {
        this.progressTicket = progressTicket;
    }

    public String getName() {
        return NbBundle.getMessage(getClass(), "ExporterGraphML_name");
    }

    public FileType[] getFileTypes() {
        FileType ft = new FileType(".graphml", NbBundle.getMessage(getClass(), "fileType_GraphML_Name"));
        return new FileType[]{ft};
    }

    public void setExportAttributes(boolean exportAttributes) {
        this.exportAttributes = exportAttributes;
    }

    public void setExportColors(boolean exportColors) {
        this.exportColors = exportColors;
    }

    public void setExportPosition(boolean exportPosition) {
        this.exportPosition = exportPosition;
    }

    public void setExportSize(boolean exportSize) {
        this.exportSize = exportSize;
    }

    public void setNormalize(boolean normalize) {
        this.normalize = normalize;
    }

    public boolean isExportAttributes() {
        return exportAttributes;
    }

    public boolean isExportColors() {
        return exportColors;
    }

    public boolean isExportPosition() {
        return exportPosition;
    }

    public boolean isExportSize() {
        return exportSize;
    }

    public boolean isNormalize() {
        return normalize;
    }

    public boolean isExportVisible() {
        return exportVisible;
    }

    public void setExportVisible(boolean exportVisible) {
        this.exportVisible = exportVisible;
    }

    public void setWriter(Writer writer) {
        this.writer = writer;
    }

    public Workspace getWorkspace() {
        return workspace;
    }

    public void setWorkspace(Workspace workspace) {
        this.workspace = workspace;
    }

    public boolean isExportHierarchy() {
        return exportHierarchy;
    }

    public void setExportHierarchy(boolean exportHierarchy) {
        this.exportHierarchy = exportHierarchy;
    }
}
TOP

Related Classes of org.gephi.io.exporter.plugin.ExporterGraphML

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.