/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@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.graph.dhns.utils; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.gephi.utils.collection.avl.ParamAVLIterator; import org.gephi.graph.dhns.core.Dhns; import org.gephi.graph.dhns.core.GraphFactoryImpl; import org.gephi.graph.dhns.core.GraphStructure; import org.gephi.graph.dhns.core.GraphVersion; import org.gephi.graph.dhns.core.GraphViewImpl; import org.gephi.graph.dhns.core.IDGen; import org.gephi.graph.dhns.core.SettingsManager; import org.gephi.graph.dhns.core.TreeStructure; import org.gephi.graph.dhns.edge.AbstractEdge; import org.gephi.graph.dhns.edge.MixedEdgeImpl; import org.gephi.graph.dhns.edge.ProperEdgeImpl; import org.gephi.graph.dhns.edge.SelfLoopImpl; import org.gephi.graph.dhns.node.AbstractNode; import org.gephi.graph.dhns.node.iterators.TreeListIterator; import org.openide.util.Exceptions; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * * @author Mathieu Bastian */ public class DHNSSerializer { private static final String ELEMENT_DHNS = "Dhns"; private static final String ELEMENT_DHNS_STATUS = "Status"; private static final String ELEMENT_EDGES = "Edges"; private static final String ELEMENT_EDGES_PROPER = "ProperEdge"; private static final String ELEMENT_EDGES_SELFLOOP = "SelfLoop"; private static final String ELEMENT_EDGES_MIXED = "MixedEdge"; private static final String ELEMENT_VIEW = "View"; private static final String ELEMENT_VIEW_NODE = "ViewNode"; private static final String ELEMENT_VIEW_EDGE = "ViewEdge"; private static final String ELEMENT_TREESTRUCTURE = "TreeStructure"; private static final String ELEMENT_TREESTRUCTURE_TREE = "Tree"; private static final String ELEMENT_TREESTRUCTURE_NODE = "Node"; private static final String ELEMENT_GRAPHVERSION = "GraphVersion"; private static final String ELEMENT_SETTINGS = "Settings"; private static final String ELEMENT_SETTINGS_PROPERTY = "Property"; private static final String ELEMENT_IDGEN = "IDGen"; public Document createDocument() { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); document.setXmlVersion("1.0"); document.setXmlStandalone(true); return document; } catch (ParserConfigurationException ex) { Exceptions.printStackTrace(ex); } return null; } public Element writeDhns(Document document, Dhns dhns) { Element dhnsE = document.createElement(ELEMENT_DHNS); Element dhnsStatusE = document.createElement(ELEMENT_DHNS_STATUS); dhnsStatusE.setAttribute("directed", String.valueOf(dhns.isDirected())); dhnsStatusE.setAttribute("undirected", String.valueOf(dhns.isUndirected())); dhnsStatusE.setAttribute("mixed", String.valueOf(dhns.isMixed())); dhnsStatusE.setAttribute("hierarchical", String.valueOf(dhns.isHierarchical())); dhnsE.appendChild(dhnsStatusE); Element idGenE = writeIDGen(document, dhns.getIdGen()); dhnsE.appendChild(idGenE); Element settingsE = writeSettings(document, dhns.getSettingsManager()); dhnsE.appendChild(settingsE); Element graphVersionE = writeGraphVersion(document, dhns.getGraphVersion()); dhnsE.appendChild(graphVersionE); Element treeStructureE = writeTreeStructure(document, dhns.getGraphStructure().getMainView()); dhnsE.appendChild(treeStructureE); Element edgesE = writeEdges(document, dhns.getGraphStructure().getMainView().getStructure()); dhnsE.appendChild(edgesE); for (GraphViewImpl view : dhns.getGraphStructure().getViews()) { if (view != dhns.getGraphStructure().getMainView()) { Element viewE = writeGraphView(document, view); dhnsE.appendChild(viewE); } } return dhnsE; } public void readDhns(Element dhnsE, Dhns dhns) { NodeList dhnsListE = dhnsE.getChildNodes(); for (int i = 0; i < dhnsListE.getLength(); i++) { if (dhnsListE.item(i).getNodeType() == Node.ELEMENT_NODE) { Element itemE = (Element) dhnsListE.item(i); if (itemE.getTagName().equals(ELEMENT_DHNS_STATUS)) { dhns.setDirected(Boolean.parseBoolean(itemE.getAttribute("directed"))); dhns.setUndirected(Boolean.parseBoolean(itemE.getAttribute("undirected"))); dhns.setMixed(Boolean.parseBoolean(itemE.getAttribute("mixed"))); } else if (itemE.getTagName().equals(ELEMENT_IDGEN)) { readIDGen(itemE, dhns.getIdGen()); } else if (itemE.getTagName().equals(ELEMENT_SETTINGS)) { readSettings(itemE, dhns.getSettingsManager()); } else if (itemE.getTagName().equals(ELEMENT_GRAPHVERSION)) { readGraphVersion(itemE, dhns.getGraphVersion()); } else if (itemE.getTagName().equals(ELEMENT_TREESTRUCTURE)) { readTreeStructure(itemE, dhns.getGraphStructure(), dhns.factory()); } else if (itemE.getTagName().equals(ELEMENT_EDGES)) { readEdges(itemE, dhns.getGraphStructure(), dhns.factory()); } else if (itemE.getTagName().equals(ELEMENT_VIEW)) { readGraphView(itemE, dhns.getGraphStructure()); } } } } public Element writeEdges(Document document, TreeStructure treeStructure) { Element edgesE = document.createElement(ELEMENT_EDGES); ParamAVLIterator<AbstractEdge> edgeIterator = new ParamAVLIterator<AbstractEdge>(); for (TreeListIterator itr = new TreeListIterator(treeStructure.getTree(), 1); itr.hasNext();) { AbstractNode node = itr.next(); for (edgeIterator.setNode(node.getEdgesOutTree()); edgeIterator.hasNext();) { AbstractEdge edge = edgeIterator.next(); Element edgeE; if (edge.isSelfLoop()) { edgeE = document.createElement(ELEMENT_EDGES_SELFLOOP); } else if (edge.isMixed()) { edgeE = document.createElement(ELEMENT_EDGES_MIXED); edgeE.setAttribute("directed", String.valueOf(edge.isDirected())); } else { edgeE = document.createElement(ELEMENT_EDGES_PROPER); } edgeE.setAttribute("source", String.valueOf(edge.getSource().pre)); edgeE.setAttribute("target", String.valueOf(edge.getTarget().pre)); edgeE.setAttribute("weight", String.valueOf(edge.getWeight())); edgeE.setAttribute("id", String.valueOf(edge.getId())); edgesE.appendChild(edgeE); } } return edgesE; } public void readEdges(Element edgesE, GraphStructure graphStructure, GraphFactoryImpl factory) { NodeList edgesListE = edgesE.getChildNodes(); TreeStructure treeStructure = graphStructure.getMainView().getStructure(); for (int i = 0; i < edgesListE.getLength(); i++) { if (edgesListE.item(i).getNodeType() == Node.ELEMENT_NODE) { Element edgeE = (Element) edgesListE.item(i); Integer id = Integer.parseInt(edgeE.getAttribute("id")); AbstractNode source = treeStructure.getNodeAt(Integer.parseInt(edgeE.getAttribute("source"))); AbstractNode target = treeStructure.getNodeAt(Integer.parseInt(edgeE.getAttribute("target"))); AbstractEdge edge; if (edgeE.getTagName().equals(ELEMENT_EDGES_PROPER)) { edge = new ProperEdgeImpl(id, source, target); } else if (edgeE.getTagName().equals(ELEMENT_EDGES_MIXED)) { edge = new MixedEdgeImpl(id, source, target, Boolean.parseBoolean(edgeE.getAttribute("directed"))); } else { edge = new SelfLoopImpl(id, source); } edge.setWeight(Float.parseFloat(edgeE.getAttribute("weight"))); edge.getEdgeData().setAttributes(factory.newEdgeAttributes(edge.getEdgeData())); edge.getEdgeData().setTextData(factory.newTextData()); source.getEdgesOutTree().add(edge); target.getEdgesInTree().add(edge); graphStructure.addToDictionnary(edge); } } graphStructure.getMainView().getStructureModifier().getEdgeProcessor().computeMetaEdges(); } public Element writeTreeStructure(Document document, GraphViewImpl view) { Element treeStructureE = document.createElement(ELEMENT_TREESTRUCTURE); treeStructureE.setAttribute("edgesenabled", String.valueOf(view.getEdgesCountEnabled())); treeStructureE.setAttribute("edgestotal", String.valueOf(view.getEdgesCountTotal())); treeStructureE.setAttribute("mutualedgesenabled", String.valueOf(view.getMutualEdgesEnabled())); treeStructureE.setAttribute("mutualedgestotal", String.valueOf(view.getMutualEdgesTotal())); treeStructureE.setAttribute("nodesenabled", String.valueOf(view.getNodesEnabled())); Element treeE = document.createElement(ELEMENT_TREESTRUCTURE_TREE); for (TreeListIterator itr = new TreeListIterator(view.getStructure().getTree(), 1); itr.hasNext();) { AbstractNode node = itr.next(); Element nodeE = document.createElement(ELEMENT_TREESTRUCTURE_NODE); nodeE.setAttribute("id", String.valueOf(node.getId())); nodeE.setAttribute("enabled", String.valueOf(node.isEnabled())); nodeE.setAttribute("pre", String.valueOf(node.pre)); nodeE.setAttribute("parent", String.valueOf(node.parent.pre)); nodeE.setAttribute("enabledindegree", String.valueOf(node.getEnabledInDegree())); nodeE.setAttribute("enabledoutdegree", String.valueOf(node.getEnabledOutDegree())); nodeE.setAttribute("enabledmutualdegree", String.valueOf(node.getEnabledMutualDegree())); treeE.appendChild(nodeE); } treeStructureE.appendChild(treeE); return treeStructureE; } public void readTreeStructure(Element treeStructureE, GraphStructure graphStructure, GraphFactoryImpl factory) { graphStructure.getMainView().setEdgesCountEnabled(Integer.parseInt(treeStructureE.getAttribute("edgesenabled"))); graphStructure.getMainView().setEdgesCountTotal(Integer.parseInt(treeStructureE.getAttribute("edgestotal"))); graphStructure.getMainView().setMutualEdgesEnabled(Integer.parseInt(treeStructureE.getAttribute("mutualedgesenabled"))); graphStructure.getMainView().setMutualEdgesTotal(Integer.parseInt(treeStructureE.getAttribute("mutualedgestotal"))); graphStructure.getMainView().setNodesEnabled(Integer.parseInt(treeStructureE.getAttribute("nodesenabled"))); NodeList nodesE = treeStructureE.getChildNodes(); NodeList nodesListE = null; TreeStructure treeStructure = graphStructure.getMainView().getStructure(); for (int i = 0; i < nodesE.getLength(); i++) { if (nodesE.item(i).getNodeType() == Node.ELEMENT_NODE) { if (((Element) nodesE.item(i)).getTagName().equals(ELEMENT_TREESTRUCTURE_TREE)) { nodesListE = ((Element) nodesE.item(i)).getChildNodes(); break; } } } if (nodesListE != null) { for (int i = 0; i < nodesListE.getLength(); i++) { if (nodesListE.item(i).getNodeType() == Node.ELEMENT_NODE) { Element nodeE = (Element) nodesListE.item(i); Boolean enabled = Boolean.parseBoolean(nodeE.getAttribute("enabled")); AbstractNode parentNode = treeStructure.getNodeAt(Integer.parseInt(nodeE.getAttribute("parent"))); AbstractNode absNode = new AbstractNode(Integer.parseInt(nodeE.getAttribute("id")), 0, 0, 0, 0, parentNode); absNode.setEnabled(enabled); Integer inDegree = Integer.parseInt(nodeE.getAttribute("enabledindegree")); Integer outDegree = Integer.parseInt(nodeE.getAttribute("enabledoutdegree")); Integer mutualDegree = Integer.parseInt(nodeE.getAttribute("enabledmutualdegree")); absNode.setEnabledInDegree(inDegree); absNode.setEnabledOutDegree(outDegree); absNode.setEnabledMutualDegree(mutualDegree); absNode.getNodeData().setAttributes(factory.newNodeAttributes(absNode.getNodeData())); absNode.getNodeData().setTextData(factory.newTextData()); treeStructure.insertAsChild(absNode, parentNode); graphStructure.addToDictionnary(absNode); } } } } public Element writeGraphView(Document document, GraphViewImpl graphView) { Element viewE = document.createElement(ELEMENT_VIEW); viewE.setAttribute("id", String.valueOf(graphView.getViewId())); viewE.setAttribute("edgesenabled", String.valueOf(graphView.getEdgesCountEnabled())); viewE.setAttribute("edgestotal", String.valueOf(graphView.getEdgesCountTotal())); viewE.setAttribute("mutualedgesenabled", String.valueOf(graphView.getMutualEdgesEnabled())); viewE.setAttribute("mutualedgestotal", String.valueOf(graphView.getMutualEdgesTotal())); viewE.setAttribute("nodesenabled", String.valueOf(graphView.getNodesEnabled())); //Nodes for (TreeListIterator itr = new TreeListIterator(graphView.getStructure().getTree(), 1); itr.hasNext();) { AbstractNode node = itr.next(); Element nodeE = document.createElement(ELEMENT_TREESTRUCTURE_NODE); nodeE.setAttribute("mainpre", String.valueOf(node.getInView(0).pre)); nodeE.setAttribute("enabled", String.valueOf(node.isEnabled())); nodeE.setAttribute("pre", String.valueOf(node.pre)); nodeE.setAttribute("parent", String.valueOf(node.parent.pre)); nodeE.setAttribute("enabledindegree", String.valueOf(node.getEnabledInDegree())); nodeE.setAttribute("enabledoutdegree", String.valueOf(node.getEnabledOutDegree())); nodeE.setAttribute("enabledmutualdegree", String.valueOf(node.getEnabledMutualDegree())); } //Edges ParamAVLIterator<AbstractEdge> edgeIterator = new ParamAVLIterator<AbstractEdge>(); for (TreeListIterator itr = new TreeListIterator(graphView.getStructure().getTree(), 1); itr.hasNext();) { AbstractNode node = itr.next(); for (edgeIterator.setNode(node.getEdgesOutTree()); edgeIterator.hasNext();) { AbstractEdge edge = edgeIterator.next(); Element edgeE = document.createElement(ELEMENT_VIEW_EDGE); edgeE.setAttribute("source", String.valueOf(node.pre)); edgeE.setAttribute("target", String.valueOf(edge.getTarget(graphView.getViewId()).pre)); edgeE.setAttribute("id", String.valueOf(edge.getId())); } } return viewE; } public void readGraphView(Element graphViewE, GraphStructure graphStructure) { GraphViewImpl graphView = graphStructure.createView(Integer.parseInt(graphViewE.getAttribute("id"))); graphView.setEdgesCountEnabled(Integer.parseInt(graphViewE.getAttribute("edgesenabled"))); graphView.setEdgesCountTotal(Integer.parseInt(graphViewE.getAttribute("edgestotal"))); graphView.setMutualEdgesEnabled(Integer.parseInt(graphViewE.getAttribute("mutualedgesenabled"))); graphView.setMutualEdgesTotal(Integer.parseInt(graphViewE.getAttribute("mutualedgestotal"))); graphView.setNodesEnabled(Integer.parseInt(graphViewE.getAttribute("nodesenabled"))); TreeStructure mainStructure = graphStructure.getMainView().getStructure(); TreeStructure treeStructure = graphView.getStructure(); NodeList nodesE = graphViewE.getChildNodes(); for (int i = 0; i < nodesE.getLength(); i++) { if (nodesE.item(i).getNodeType() == Node.ELEMENT_NODE) { if (((Element) nodesE.item(i)).getTagName().equals(ELEMENT_VIEW_NODE)) { Element nodeViewE = (Element) nodesE.item(i); Boolean enabled = Boolean.parseBoolean(nodeViewE.getAttribute("enabled")); AbstractNode mainNode = mainStructure.getNodeAt(Integer.parseInt(nodeViewE.getAttribute("mainpre"))); AbstractNode parentNode = treeStructure.getNodeAt(Integer.parseInt(nodeViewE.getAttribute("parent"))); AbstractNode node = new AbstractNode(mainNode.getNodeData(), graphView.getViewId(), 0, 0, 0, parentNode); Integer inDegree = Integer.parseInt(nodeViewE.getAttribute("enabledindegree")); Integer outDegree = Integer.parseInt(nodeViewE.getAttribute("enabledoutdegree")); Integer mutualDegree = Integer.parseInt(nodeViewE.getAttribute("enabledmutualdegree")); node.setEnabledInDegree(inDegree); node.setEnabledOutDegree(outDegree); node.setEnabledMutualDegree(mutualDegree); node.setEnabled(enabled); treeStructure.insertAsChild(node, parentNode); } else if (((Element) nodesE.item(i)).getTagName().equals(ELEMENT_VIEW_EDGE)) { Element edgeViewE = (Element) nodesE.item(i); AbstractEdge edge = graphStructure.getEdgeFromDictionnary(Integer.parseInt(edgeViewE.getAttribute("id"))); AbstractNode source = treeStructure.getNodeAt(Integer.parseInt(edgeViewE.getAttribute("source"))); AbstractNode target = treeStructure.getNodeAt(Integer.parseInt(edgeViewE.getAttribute("target"))); source.getEdgesOutTree().add(edge); target.getEdgesInTree().add(edge); } } } graphView.getStructureModifier().getEdgeProcessor().computeMetaEdges(); } public Element writeGraphVersion(Document document, GraphVersion graphVersion) { Element graphVersionE = document.createElement(ELEMENT_GRAPHVERSION); graphVersionE.setAttribute("node", String.valueOf(graphVersion.getNodeVersion())); graphVersionE.setAttribute("edge", String.valueOf(graphVersion.getEdgeVersion())); return graphVersionE; } public void readGraphVersion(Element graphVersionE, GraphVersion graphVersion) { int nodeVersion = Integer.parseInt(graphVersionE.getAttribute("node")); int edgeVersion = Integer.parseInt(graphVersionE.getAttribute("edge")); graphVersion.setVersion(nodeVersion, edgeVersion); } public Element writeSettings(Document document, SettingsManager settingsManager) { Element settingsE = document.createElement(ELEMENT_SETTINGS); for (Entry<String, Object> entry : settingsManager.getClientProperties().entrySet()) { Element propertyE = document.createElement(ELEMENT_SETTINGS_PROPERTY); propertyE.setAttribute("key", entry.getKey()); ByteArrayOutputStream stream = new ByteArrayOutputStream(); XMLEncoder xmlEncoder = new XMLEncoder(stream); xmlEncoder.writeObject(entry.getValue()); xmlEncoder.close(); propertyE.setAttribute("value", stream.toString()); settingsE.appendChild(propertyE); } return settingsE; } public void readSettings(Element settingsE, SettingsManager settingsManager) { NodeList propertiesE = settingsE.getChildNodes(); for (int i = 0; i < propertiesE.getLength(); i++) { if (propertiesE.item(i).getNodeType() == Node.ELEMENT_NODE) { Element propertyE = (Element) propertiesE.item(i); String key = propertyE.getAttribute("key"); String valueXML = propertyE.getAttribute("value"); XMLDecoder xmlDecoder = new XMLDecoder(new ByteArrayInputStream(valueXML.getBytes())); Object value = xmlDecoder.readObject(); settingsManager.putClientProperty(key, value); } } } public Element writeIDGen(Document document, IDGen idGen) { Element idGenE = document.createElement(ELEMENT_IDGEN); idGenE.setAttribute("node", String.valueOf(idGen.getNodeGen())); idGenE.setAttribute("edge", String.valueOf(idGen.getEdgeGen())); return idGenE; } public void readIDGen(Element idGenE, IDGen idGen) { int nodeGen = Integer.parseInt(idGenE.getAttribute("node")); int edgeGen = Integer.parseInt(idGenE.getAttribute("edge")); idGen.setNodeGen(nodeGen); idGen.setEdgeGen(edgeGen); } }