/** RoadNetwork.java -- classes that describe a road network * @author Douglas Jones * @version 2017-02-10 */ import java.util.LinkedList; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; /** Utility package for error handling */ class Errors { private Errors(){}; // you may never instantiate this class /** Call this to warn of non fatal errors */ public static void warn( String message ) { System.err.println( "Warning: " + message ); } /** Call this to report fatal errors */ public static void fatal( String message ) { System.err.println( "Fatal error: " + message ); System.exit( -1 ); } } /** Roads link intersections * @see Intersection * @see Errors * @see RoadNetwork#findRoad(String) */ class Road { private final float travelTime; // how long to travel down road private final Intersection destination; // where road goes, or null private final Intersection source; // source of road, or null // Road name is the source-destination names /** initializer scans and processes one road definition */ public Road( Scanner sc, LinkedList inters ) { String srcName = sc.next(); String dstName = sc.next(); source = RoadNetwork.findIntersection( srcName ); if (source == null) { Errors.warn( "Road '" + srcName + "' '" + dstName + "' source undefined." ); } destination = RoadNetwork.findIntersection( srcName ); if (destination == null) { Errors.warn( "Road '" + srcName + "' '" + dstName + "' destination undefined." ); } // Bug: What if there is no next float? travelTime = sc.nextFloat(); sc.nextLine(); } /** output this road in a format like that used for input */ public String toString() { String srcName; String dstName; if (source == null) { srcName = "???"; } else { srcName = source.name; } if (destination == null) { dstName = "???"; } else { dstName = destination.name; } return( "road " + srcName + " " + dstName + " " + travelTime ); } } /** Intersections are linked by one-way roads * @see Road * @see RoadNetwork#findRoad(String) */ class Intersection { private final LinkedList outgoing = new LinkedList (); // Bug: Does the intersection need a list of incoming roads? public final String name; // the name of the intersection /** initializer scans and processes one intersection definition */ public Intersection( Scanner sc, LinkedList inters ) { name = sc.next(); if (RoadNetwork.findIntersection( name ) != null) { Errors.warn( "Intersection '" + name + "' redefined."); } sc.nextLine(); } /** output this Intersection in a format like that used for input */ public String toString() { return( "intersection " + name ); } } class Vehicle { // Bug: does this go here? } class Event { // Bug: does this go here? } /** RoadNetwork -- main program that reads and writes a road network * @see Road * @see Intersection * @see Errors * @see #main */ public class RoadNetwork { // lists of roads and intersectins static LinkedList roads = new LinkedList (); static LinkedList inters = new LinkedList (); /** utility method to look up an intersection by name * @param s is the name of the intersection, a string * @return is the Intersection object with that name */ public static Intersection findIntersection( String s ) { for ( Intersection i: inters ) { if (i.name.equals( s )) return i; } return null; } /** read a road network */ public static void initializeNetwork( Scanner sc ) { while (sc.hasNext()) { // until we hit the end of the file String command = sc.next(); if (("intersection".equals( command )) || ("i".equals( command )) ) { inters.add( new Intersection( sc, inters ) ); } else if (("road".equals( command )) || ("r".equals( command )) ) { roads.add( new Road( sc, inters ) ); } else if ("--".equals( command )) { // comment sc.nextLine(); // skip it all } else { Errors.warn( "Command '" + command + "' is not road or intersection" ); } } } /** write out a road network */ public static void writeNetwork() { for ( Intersection i: inters ) { System.out.println( i.toString() ); } for ( Road r: roads ) { System.out.println( r.toString() ); } } /** main program that reads and writes a road network * @param args the command line arguments must hold one file name */ public static void main( String[] args ) { // verify that the argument exists. if (args.length < 1) { Errors.fatal( "Missing file name on command line" ); } else if (args.length > 1) { Errors.fatal( "Unexpected command line args" ); } else try { initializeNetwork( new Scanner( new File( args[0] ) ) ); writeNetwork(); } catch (FileNotFoundException e) { Errors.fatal( "Could not read '" + args[0] + "'" ); } } }