/* Road Network Simulator * Author: Douglas Jones * Status: Compiles and works, but is full of bugs * Version: 9/16/2020 */ import java.util.LinkedList; import java.util.Iterator; import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; // Utility classes /** * Error handling */ class Error{ // BUG: Perhaps we should count warnings public static void warn( String message ) { System.err.println( message ); // BUG: Perhaps count warnings and error out if too many } public static void fatal( String message ) { warn( message ); System.exit( 1 ); } } /** * Roads connect intersections * @see Intersection */ class Road { // instance variables private final float travelTime; private final Intersection destination; private final Intersection source; // the collection of all instances private static final LinkedList allRoads = new LinkedList (); /** The only constructor * @param sc Scanner from which description comes * Input format scanned from sc: source-name destination-name travel-time *
where source-name is the name of the source intersection and *
destination-name is the name of the destination intersection and *
travel-time is a floating point time in seconds */ public Road( Scanner sc ) { // keyword Road was already scanned final String src; // where does it come from final String dst; // where does it go if (sc.hasNext()) { src = sc.next(); } else { Error.warn( "road source missing\n" ); src = "???"; } if (sc.hasNext()) { dst = sc.next(); } else { Error.warn( "road " + src + " to missing destination\n" ); dst = "???"; } if (sc.hasNextFloat()) { travelTime = sc.nextFloat(); } else { Error.warn( "road " + src + " " + dst + " missing travel time\n" ); travelTime = Float.NaN; } destination = Intersection.lookup( dst ); source = Intersection.lookup( dst ); // BUG: What if lookup returns null! allRoads.add( this ); // this is the only place items are added! } /** Primarily for debugging * @return textual name and travel time of the road */ public String toString() { return source.name + " " + destination.name + " " + travelTime; } /** Allow outsiders to iterate over all roads * @return iterator over roads */ public static Iterator iterator() { return allRoads.iterator(); } } /** * Intersections are connected by roads * @see Road */ class Intersection { // instance variables final String name; private final LinkedList outgoing = new LinkedList (); private final LinkedList incoming = new LinkedList (); // the collection of all instances private static final LinkedList allIntersections = new LinkedList (); /** The only constructor for Intersection * @arg sc the scanner from which the Intersection description is scanned * Input format scanned from sc: name *
where name is a string */ public Intersection( Scanner sc ) { name = sc.next(); // pick off name of intersection; // BUG: Must Detect duplicate definitions of intersections? // BUG: Intersection type? Other attributes? Handle this later. allIntersections.add( this ); } /** Primarily for debugging * @return textual name and travel time of the road */ public String toString() { return name; // BUG: Other attributes? } /** Allow outsiders to iterate over all roads * @return iterator over roads */ public static Iterator iterator() { return allIntersections.iterator(); } /** Allow finding intersections by name * @return road that has this name or null if none do */ public static Intersection lookup( String n ) { for (Intersection i: allIntersections) { if (i.name.equals( n )) return i; } return null; } } /** * Main class builds model and will someday simulate it * @see Road * @see Intersection */ public class RoadNetwork { private static void readNetwork( Scanner sc ) { while (sc.hasNext()) { // until the input file is finished String command = sc.next(); if ("intersection".equals( command )) { new Intersection( sc ); } else if ("road".equals( command )) { new Road( sc ); } else { Error.warn( "unknown command: " + command + "\n" ); } } } private static void writeNetwork() { for (Iterator i = Intersection.iterator(); i.hasNext(); ){ System.out.println( "Intersection " + i.next() ); } for (Iterator i = Road.iterator(); i.hasNext(); ){ System.out.println( "Road" + i.next() ); } } public static void main( String[] args ) { if (args.length < 1) { Error.fatal( "Missing file name argument\n" ); } else try { readNetwork( new Scanner( new File( args[0] ) ) ); writeNetwork(); // BUG -- this code is for debugging only // BUG -- simulation code goes here if readNetwork success } catch ( FileNotFoundException e) { Error.fatal( "Can't open file: " + args[0] + "\n" ); } } }