// RoadNetwork.java /** * Classes that define the topology of a road network. * @author Douglas Jones * @version MP1? */ import java.util.LinkedList; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; class Errors { /** Error reporting framework */ static void fatal( String message ) { /** Report a fatal error with the given message */ System.err.println( message ); System.exit( 1 ); } } class SyntaxCheck { /** Syntax checking support */ static void lineEnd( Scanner sc, String c ) { /** Check for end of line on sc, * Use c to provide context in any error message */ String s = sc.nextLine(); if (!s.isEmpty()) { Errors.fatal( c + " has non-empty line end '" + s + "'" ); } } } class Road { /** Roads are one-way streets linking intersections * @see Intersection */ float travelTime; //measured in seconds Intersection destination; //where the road goes Intersection source; //where the comes from // name of road is source-destination // initializer public Road( Scanner sc ) { /** Initialize a road by scanning its description from sc */ String srcName = sc.next(); source = RoadNetwork.findIntersection( srcName ); String dstName = sc.next(); destination = RoadNetwork.findIntersection( dstName ); if (source == null) { Errors.fatal( "Road '" + srcName + "' '" + dstName + "'" + "-- the first name is undefined" ); } if (destination == null) { Errors.fatal( "Road '" + srcName + "' '" + dstName + "'" + "-- the second name is undefined" ); } // Bug: should we add this to source.outgoing list? // Bug: should we add this to destination.incoming list? if (!sc.hasNextFloat()) { Errors.fatal( "Road '" + srcName + "' '" + dstName + "'" + "-- travel time not specified" ); } travelTime = sc.nextFloat(); SyntaxCheck.lineEnd( sc, "Road '" + srcName + "' '" + dstName + "'" ); } public String toString() { /** Convert a road back to its textual description */ return "road " + source.name + ' ' + destination.name + ' ' + travelTime ; } } class Intersection { /** Intersections join roads * @see Road */ String name; LinkedList outgoing = new LinkedList (); LinkedList incoming = new LinkedList (); // Bug: the above two lists are unused, but we think we'll need them. // Bug: multiple types of intersections (uncontrolled, stoplight, ...) // initializer public Intersection( Scanner sc, LinkedList inters ) { /** Initialize an interseciton scanning its description from sc */ name = sc.next(); if (RoadNetwork.findIntersection( name ) != null) { Errors.fatal( "Intersection '" + name + "' redefined" ); } SyntaxCheck.lineEnd( sc, "Intersection '" + name + "'" ); } public String toString() { /** Convert an intersection back to its textual description */ return "intersection " + name; } } class Vehicle { /** Vehicles travel on roads through intersections * @see Intersection * @see Road */ // Bug: do I need my current location? } class Event { /** Events mark arrival of vehicles at Intersections. * @see Intersection * @see Vehicle */ float time; //when the vehicle arrives Intersection place; //where vehicle arrives // Bug: is this right? There may be many queues at intersection // Bug: how do we know which queue the road leads to? } public class RoadNetwork { /** Top level description of a road network consisting of * some intersections connected by some roads. * @see Intersection * @see Road */ static LinkedList inters = new LinkedList (); static LinkedList roads = new LinkedList (); static Intersection findIntersection( String s ) { /** Given s the name of a particular intersection, * returns null if that intersection does not exist, * returns that intersection if it exists. * @see Intersection */ // Bug: Reengineering this to use a hash should be possible for (Intersection i: inters) { if (i.name.equals( s )) { return i; } } return null; } private static void readNetwork( Scanner sc ) { /** Read a road network, scanning its description from sc. */ while (sc.hasNext()) { // until the input file is finished String command = sc.next(); if (command.equals( "intersection" ) || command.equals( "i" ) ) { // Bug: Something about an intersection inters.add( new Intersection( sc, inters ) ); } else if (command.equals( "road" ) || command.equals( "r" ) ) { // Bug: Something about a road roads.add( new Road( sc ) ); } else { Errors.fatal( "'" + command + "' not a road or intersection" ); } } } private static void writeNetwork() { /** Write out a textual description of the entire road network. * This routine is scaffolding used during development. */ for (Intersection i: inters) { System.out.println( i.toString() ); } for (Road r: roads) { System.out.println( r.toString() ); } } public static void main(String[] args) { /** Create a road network. * The command line argument names the input file. * For now, the output is just a reconstruction of the input. */ if (args.length < 1) { Errors.fatal( "Missing filename argument" ); } if (args.length > 1) { Errors.fatal( "Extra command-line arguments" ); } try { readNetwork( new Scanner( new File( args[0] ))); writeNetwork(); } catch (FileNotFoundException e) { Errors.fatal( "Can't open file '" + args[0] + "'" ); } } }