/Users/petercappello/NetBeansProjects/56-2014/56-2014-FileIO/src/Graph.java
import java.awt.Point;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.DataFormatException;

/**
 *
 * @author Peter Cappello
 */
public class Graph implements Processor
{
    private final Map<Integer, List<Integer>> mapVvertexToAdjacencyList = new HashMap<>();
    
    /**
     * Reads a graph from a text file.
     * @throws IOException
     * @throws DataFormatException when the text file does not conform to the 
     * format: 1 edge per line, where the edge is represented by 2 integers,
     * each is the name of its vertex (.e., "24 78" represents the edge from
     * vertex 24 to vertex 78.
     */
    public void readGraph() throws IOException, DataFormatException
    {
        TextFileProcessor textFileProcessor = new TextFileProcessor( null );
        textFileProcessor.readFile( this );
    }
    
    /**
     * Writes the graph to a text file, 1 edge per line.
     * @throws IOException 
     */
    public void writeGraph() throws IOException
    {
        TextFileProcessor textFileProcessor = new TextFileProcessor( null );
        textFileProcessor.writeFile( this );
    }
    
    @Override
    public void processInputLine( String string ) throws DataFormatException 
    {
        addEdge( makeEdge( string ) );
    }
    
    /**
     *
     * @param writer
     * @throws IOException
     */
    @Override
    public void processOutputLines( Writer writer ) throws IOException
    {
        String line = null;
        for ( Integer vertexV : mapVvertexToAdjacencyList.keySet() )
        {
            List<Integer> adjacencyList = mapVvertexToAdjacencyList.get( vertexV );
            {
                for ( Integer vertexW : adjacencyList )
                {
                   writer.write( vertexV + " " + vertexW );
                   writer.write( '\n' );
                    System.out.println( vertexV + " " + vertexW );
                }
            }
        }
    }
    
    private Point makeEdge( String line ) throws DataFormatException
    {
        String[] vertices = line.split( "\\s" );
        if ( vertices.length != 2 )
        {
            throw new DataFormatException( line + "  should contain exactly 2 integers");
        }
        try
        {
            int vertexV = Integer.parseInt( vertices[ 0 ] );
            int vertexW = Integer.parseInt( vertices[ 1 ] );
            return new Point( vertexV, vertexW );
        }
        catch ( NumberFormatException exception )
        {
            String msg = "One of the following is not intepretible as an integer: " 
                       + vertices[ 0 ] + " " + vertices[ 1 ];
            throw new NumberFormatException( msg );
        }
    }
    
    private void addEdge( Point edge )
    {
        addEdge( edge.x, edge.y );
        addEdge( edge.y, edge.x );
    }
    
    private void addEdge( int v, int w )
    {
        List<Integer> edgeList = mapVvertexToAdjacencyList.get( v );
        if ( edgeList == null )
        {
            edgeList = new ArrayList();
            mapVvertexToAdjacencyList.put( v, edgeList );
        }
        assert edgeList != null;
        edgeList.add( w );
    }
    
    public static void main( String[] args ) throws IOException, DataFormatException
    {
        Graph graph = new Graph();
        System.out.println( "Reading graph ..." );
        graph.readGraph();
        System.out.println(" Number of vertices: " + graph.mapVvertexToAdjacencyList.size() );
        System.out.println(  "Writing graph ..." );
        graph.writeGraph();
    }
}