source: tmcsimulator/trunk/src/tmcsim/client/ATMSDriverClient.java @ 109

Revision 109, 11.5 KB checked in by jdalbey, 9 years ago (diff)

ATMSDriverClient.java Enhanced to call ConsoleDriver? methods to update highway colors. Removed redundant code in Station..java.

Line 
1package tmcsim.client;
2
3import atmsdriver.ConsoleDriver;
4import atmsdriver.model.Highways;
5import atmsdriver.model.Station;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.io.FileInputStream;
9import java.io.FileNotFoundException;
10import java.rmi.Naming;
11import java.rmi.RemoteException;
12import java.rmi.server.UnicastRemoteObject;
13import java.util.LinkedList;
14import java.util.Properties;
15import java.util.Queue;
16import java.util.Scanner;
17import java.util.concurrent.TimeUnit;
18import java.util.logging.Level;
19import java.util.logging.Logger;
20import javax.swing.JOptionPane;
21import javax.swing.JWindow;
22import javax.swing.Timer;
23import javax.swing.UIManager;
24import tmcsim.common.SimulationException;
25import tmcsim.interfaces.CADClientInterface;
26import tmcsim.interfaces.CoordinatorInterface;
27
28/**
29 * Skeleton for ATMS Driver that reads a "batch" file of highway
30 * status update commands.
31 * It operates as a client of the
32 * CAD server, using RMI to poll the server every second for the current
33 * simulation clock time.  It uses the simulation clock time
34 * to fire update commands at the desired time.
35 * Note: Sim Mgr must be running before starting this application.
36 *
37 * @author jdalbey
38 */
39public class ATMSDriverClient extends UnicastRemoteObject implements
40        CADClientInterface
41{
42    private static final String CONFIG_FILE_NAME = "cad_client_config.properties";
43    private final static int ONE_SECOND = 1000;
44    /**
45     * Error logger.
46     */
47    private static Logger cadClientLogger = Logger.getLogger("tmcsim.client");
48
49    @Override
50    public void refresh() throws RemoteException
51    {
52        throw new UnsupportedOperationException("Not supported yet.");
53    }
54
55    /**
56     * Enumeration containing properties name values. See CADClient class
57     * description for more information.
58     *
59     * @author Matthew Cechini
60     * @see CADClient
61     */
62    private static enum PROPERTIES
63    {
64        CAD_SIM_HOST("CADSimulatorHost"), CAD_SIM_PORT("CADSimulatorSocketPort"), CAD_RMI_PORT(
65        "CADRmiPort"), CLIENT_CAD_POS("CADPosition"), CLIENT_USER_ID(
66        "CADUserID"), KEYBOARD_TYPE("KeyboardType"), DISPLAY_TYPE(
67        "DisplayType");
68        public String name;
69
70        private PROPERTIES(String n)
71        {
72            name = n;
73        }
74    }
75    /**
76     * CADClientSocket Object to handle socket communication between the Client
77     * and CAD Simulator.
78     */
79    private CADClientSocket theClientSocket;
80
81    /**
82     * Properties object for the CADClient class.
83     */
84    private Properties cadClientProp;
85    /**
86     * RMI interface for communication with the remote Coordinator.
87     */
88    private static CoordinatorInterface theCoorInt;
89    /**
90     * reference to itself to be used for disconnecting from CADSimulator
91     */
92    private CADClientInterface client = this;
93   
94    /**
95     * Queue of batch events
96     */
97    private Queue<String> eventQueue;
98   
99    /** Instance of ConsoleDriver that contains the highway model */
100    private ConsoleDriver console;
101
102    /**
103     * Constructor. Initialize data from parsed properties file. Create a socket
104     * connection to the CADSimulator.
105     *
106     * @param propertiesFile File path (absolute or relative) to the properties
107     * file containing configuration data.
108     */
109    public ATMSDriverClient(String propertiesFile) throws SimulationException,
110            RemoteException
111    {
112        if (!verifyProperties(propertiesFile))
113        {
114            System.exit(0);
115        }
116        Highways highways = new Highways(
117        "config/vds_data/lds.txt",
118        "config/vds_data/loop.txt",
119        "config/vds_data/highwaysMeta.txt",
120        "localhost", 8080);
121        console = new ConsoleDriver(highways);
122       
123        connect(cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name).trim(),
124                cadClientProp.getProperty(PROPERTIES.CAD_RMI_PORT.name).trim());
125
126        // READ THE BATCH FILE OF COMMANDS and put in a queue
127        readBatchFile();
128        // Consider special cases:  1) time to fire first command
129        // has already past when application starts.
130        // 2.  Two commands have same fire time specified.
131        // 3.  How to "override" a command, to clear an incident.
132       
133        // Create a timer that fetches the simulation time every second.
134        Timer timer = new Timer(ONE_SECOND, new ActionListener()
135        {
136            public void actionPerformed(ActionEvent e)
137            {
138                String currentClock = "";
139                try
140                {
141                    long simtime = theCoorInt.getCurrentSimulationTime();
142                    currentClock = formatInterval(simtime);
143                    System.out.println("Current clock: " + currentClock);
144                } catch (RemoteException ex)
145                {
146                    Logger.getLogger(ATMSDriverClient.class.getName()).log(Level.SEVERE, null, ex);
147                }
148                if (!eventQueue.isEmpty())
149                {
150                    // Check the queue of commands to see if the first
151                    // item matches the current time.  IF so,
152                    // issue that command and remove it from queue.
153                    String nextEvent = eventQueue.peek();
154                    String eventTime = nextEvent.substring(0,8);
155                    System.out.println("Next event will be launched at: " + eventTime);
156                    if (eventTime.equals(currentClock))
157                    {
158                        System.out.println("LAUNCHING EVENT at " + nextEvent );
159                        // Extract fields from event and prepare them
160                        Scanner lineScan = new Scanner(nextEvent);
161                        lineScan.next(); // skip time field
162                        int routeNumber = lineScan.nextInt();
163                        Station.DIRECTION dir = Station.DIRECTION.toDirection(lineScan.next());
164                        double postmile = lineScan.nextDouble();
165                        int range = lineScan.nextInt();
166                        ConsoleDriver.DOTCOLOR dotcolor = ConsoleDriver.DOTCOLOR.toDotColor(lineScan.next());
167                        // apply colorization to highways
168                        console.applyColorToHighwayStretch(routeNumber, dir, postmile, range, dotcolor);
169                        // Remove this event from the queue, we're done with it.
170                        eventQueue.remove();
171                    }
172                }
173            }
174        });
175        timer.start();
176
177        ensureProperShutdown();
178    }
179
180    private void readBatchFile()
181    {
182        FileInputStream fis;
183        try {
184            fis = new FileInputStream("config/vds_data/atmsBatchEvents.txt");
185            Scanner scan = new Scanner(fis);
186            eventQueue = new LinkedList<String>();
187            while (scan.hasNext())
188            {
189                eventQueue.add(scan.nextLine());
190            }
191        } catch (FileNotFoundException ex) {
192            Logger.getLogger(ATMSDriverClient.class.getName()).log(Level.SEVERE, null, ex);
193        }
194    }
195   
196    /**
197     * Connect to the Coordinator's RMI object, and register this object for
198     * callback with the Coordinator.
199     *
200     * @param hostname Host name of the CAD Simulator.
201     * @param portNumber Port number of the CAD Simulator RMI communication.
202     * @throws SimulationException if there is an error creating the RMI
203     * connection.
204     */
205    protected void connect(String hostname, String portNumber)
206            throws SimulationException
207    {
208
209        String coorIntURL = "";
210
211        try
212        {
213            coorIntURL = "rmi://" + hostname + ":" + portNumber
214                    + "/coordinator";
215            theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
216            theCoorInt.registerForCallback(this);
217        } catch (Exception e)
218        {
219            throw new SimulationException(SimulationException.CAD_SIM_CONNECT,
220                    e);
221        }
222    }
223
224    /**
225     * This method verifies that the CAD Simulator Host and Port values are not
226     * null. Also, if a CAD Position or User ID do not exist in the properties
227     * file, the user is prompted to enter values. These values are written to
228     * the properties file. If the user cancels the process of entering these
229     * values, the verification fails.
230     *
231     * @param propertiesFile File path (absolute or relative) to the properties
232     * file containing configuration data.
233     * @return True if the properties file is valid, false if not.
234     * @throws SimulationException if there is an exception in verifying the
235     * properties file, or if the user cancels input.
236     */
237    private boolean verifyProperties(String propertiesFile)
238            throws SimulationException
239    {
240
241        // Load the properties file.
242        try
243        {
244            cadClientProp = new Properties();
245            cadClientProp.load(new FileInputStream(propertiesFile));
246        } catch (Exception e)
247        {
248            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
249                    "Constructor", "Exception in reading properties file.", e);
250
251            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
252                    e);
253        }
254
255
256        // Ensure that the properties file does not have null values for the
257        // CAD Simulator's connection information.
258        if (cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name) == null
259                || cadClientProp.getProperty(PROPERTIES.CAD_SIM_PORT.name) == null)
260        {
261            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
262                    "Constructor", "Null value in properties file.");
263            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
264        }
265
266        return true;
267    }
268
269    /**
270     * Format a time in seconds as HH:MM:SS
271     *
272     * @param l
273     * @return
274     */
275    private String formatInterval(final long l)
276    {
277        final long hr = TimeUnit.SECONDS.toHours(l);
278        final long min = TimeUnit.SECONDS.toMinutes(l - TimeUnit.HOURS.toSeconds(hr));
279        final long sec = TimeUnit.SECONDS.toSeconds(l - TimeUnit.HOURS.toSeconds(hr) - TimeUnit.MINUTES.toSeconds(min));
280        return String.format("%02d:%02d:%02d", hr, min, sec);
281    }
282
283    public void ensureProperShutdown()
284    {
285        Runtime.getRuntime().addShutdownHook(new Thread()
286        {
287            public void run()
288            {
289                try
290                {
291                    theCoorInt.unregisterForCallback(client);
292                } catch (RemoteException e)
293                {
294                    e.printStackTrace();
295                }
296            }
297        });
298    }
299
300    /**
301     * Construct the CADClient with the properties file path, either from the
302     * command line arguments or default.
303     *
304     * @param args Command line arguments.
305     */
306    public static void main(String[] args)
307    {
308        if (System.getProperty("CONFIG_DIR") == null)
309        {
310            System.setProperty("CONFIG_DIR", "config");
311        }
312
313        try
314        {
315            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
316            new ATMSDriverClient(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME);
317
318        } catch (Exception e)
319        {
320            cadClientLogger.logp(Level.SEVERE, "SimulationManager", "Main",
321                    "Error initializing application.");
322
323            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
324                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
325
326            System.exit(-1);
327        }
328
329    }
330}
Note: See TracBrowser for help on using the repository browser.