/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotools.graph.io.standard;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Iterator;
import org.geotools.graph.build.GraphBuilder;
import org.geotools.graph.io.GraphReaderWriter;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Graph;
import org.geotools.graph.structure.Node;
/**
* An implementation of GraphReaderWriter that uses java serialization to
* read and write graph objects. During the graph serialization process
* edges are written to the object output stream. Along with the edges,
* the two nodes incident to the edge are also written. However, edge adjacency
* lists of nodes are <B>not</B> written to the output stream in order to
* prevent deep recursive calls that often result in a stack overflow. Therefore
* it is important that any implementation of the Node interface declare its
* edge adjacecny list (if any) as transient in order to support graph
* serializability. <BR>
* Because edge adjacency lists are not serialized, they must be reconstructed
* upon deserialization in order to preserve the original graph structure.<BR>
*
* @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
*
*
* @source $URL$
*/
public class SerializedReaderWriter extends AbstractReaderWriter
implements FileReaderWriter {
/**
* Deserializes the graph and reconstructs the original structure.
*
* @see GraphReaderWriter#read()
*/
public Graph read() throws Exception {
//read builder property
GraphBuilder builder = (GraphBuilder)getProperty(BUILDER);
//create file input stream
ObjectInputStream objin = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream((String)getProperty(FILENAME))
)
);
//read header
int nnodes = objin.readInt();
int nedges = objin.readInt();
//rebuild edge collection, upon reading an edge, at the edge to the
// adjacency list of each of its nodes
int count = 0;
while(count++ < nedges) {
Edge e = (Edge)objin.readObject();
e.getNodeA().setVisited(false);
e.getNodeB().setVisited(false);
builder.addEdge(e);
}
//rebuild node collection
for (
Iterator itr = builder.getGraph().getEdges().iterator(); itr.hasNext();
) {
Edge e = (Edge)itr.next();
if (!e.getNodeA().isVisited()) {
e.getNodeA().setVisited(true);
builder.addNode(e.getNodeA());
}
if (!e.getNodeB().isVisited()) {
e.getNodeB().setVisited(true);
builder.addNode(e.getNodeB());
}
}
//check if object stream is empty, if not, there are nodes of degree 0
// in the graph
try {
Node n;
while((n = (Node)objin.readObject()) != null) {
builder.addNode(n);
}
}
catch(EOFException ignore) {}
return(builder.getGraph());
}
/**
* Serializes the graph by writing each edge in the graph to an object
* output stream. If there any nodes of degree 0 in the graph, then they are
* appended to the end of the object output stream.
*
* @see GraphReaderWriter#write()
*/
public void write(Graph graph) throws Exception {
//create file output stream
ObjectOutputStream objout = new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream((String)getProperty(FILENAME))
)
);
//create header
// 1. number of nodes
// 2. number of edges
objout.writeInt(graph.getNodes().size());
objout.writeInt(graph.getEdges().size());
//write out edges (note: nodes do not write out adjacent edges)
for (Iterator itr = graph.getEdges().iterator(); itr.hasNext();) {
Edge e = (Edge)itr.next();
objout.writeObject(e);
}
//write out any nodes that have no adjacent edges
for (Iterator itr = graph.getNodesOfDegree(0).iterator(); itr.hasNext();) {
Node n = (Node)itr.next();
objout.writeObject(n);
}
objout.flush();
objout.close();
}
}