// RoadNetwork.java // author Doug Jones // version 2019-02-06 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.List; import java.util.LinkedList; import java.util.Scanner; /** Error reporting package * Provide a standard prefix and behavior for error reporting * @author Douglas W. Jones * @version 2019-01-21 */ class Errors { /** Prefix string for error messages */ private static String prefix = "??: "; /** Set prefix on error reports, should be done before any error reports * @arg p the prefix on any error messages */ public static void setPrefix( String p ) { prefix = p; } /** Report nonfatal errors, output a message and return * @arg m the message to output */ public static void warn( String m ) { System.err.println( prefix + ": " + m ); } } /** Roads are one-way paths between Intersections * @author Douglas Jones * @version 2019-02-06 * @see Intersection */ class Road { private float travelTime; // how long it takes to get to the other end private Intersection destination; // where does this road go private Intersection source; // where does this road come from // Bug Need attributes of a road /** construct a new Road * @param sc the scanner used to get the attributes of this road * When called, the keyword "road" has already been scanned, * so we are ready to scan the source and destination plus other stuff. */ public Road( Scanner sc ) { // Bug -- what if there is no next String srcName = sc.next(); // Bug -- what if there is no next String dstName = sc.next(); source = RoadNetwork.findIntersection( srcName ); destination = RoadNetwork.findIntersection( dstName ); // Bug -- what if source is null // Bug -- what if destination is null // Bug -- what if there is no next float travelTime = sc.nextFloat(); } public String toString() { return "Road " + source.name + ' ' + destination.name + ' ' + travelTime; } } /** Intersections are joined by Roads * @author Douglas Jones * @version 2019-02-06 * @see Road */ class Intersection { /** The name of this interseciton */ public String name; // where this intersection connects LinkedList outgoing = new LinkedList (); // Bug do we need to know what roads lead here? // Bug how about different kinds of intersections /** construct a new Intersection * @param sc the scanner used to get the attributes of this intersection * When called, the keyword "intersection" has already been scanned, * so we are ready to scan the additional attributes, if any. */ public Intersection( Scanner sc ) { // Bug -- what if there is no next token? name = sc.next(); if (RoadNetwork.findIntersection( name ) != null) { Errors.warn( "Name reused for intersection " + name ); name = "reused-" + name; } // Bug -- what what about other attributes? } public String toString() { return "Intersection " + name; } } public class RoadNetwork { // lists of all the parts of this model private static List intersections = new LinkedList (); private static List roads = new LinkedList (); /** look up an intersection by name * @param n the name of the intersection * @returns the Intersection with that name */ public static Intersection findIntersection( String n ) { // stupid code, a linear search, but does it matter? for (Intersection i: intersections) { if (i.name.equals( n )) return i; } return null; } // build the road network by scanning a source file private static void buildNetwork( Scanner sc ) { // Bug -- what if there is no next while (sc.hasNext()) { // pick off the next part of the network description String command = sc.next(); if ("intersection".equals( command )) { intersections.add( new Intersection( sc ) ); } else if ("road".equals( command )) { roads.add( new Road( sc ) ); } // Bug -- what if it was neither of the above, should we complain? // Bug -- it would be nice to allow some kind of comments } } // print out the entire road network private static void printNetwork() { for (Intersection i: intersections) { System.out.println( i ); } for (Road r: roads) { System.out.println( r ); } } public static void main( String[] args ) { Errors.setPrefix( "RoadNetwork" ); if (args.length < 1) { Errors.warn( "missing argument" ); System.exit( 1 ); } if (args.length > 1) { Errors.warn( "extra arguments" ); } try { // args[0] is the text file holding the road network, buildNetwork( new Scanner( new FileInputStream( args[0] ) ) ); printNetwork(); // something testable! } catch( FileNotFoundException e ) { Errors.warn( "can't open file" ); System.exit( 1 ); } } }