Warning: Can't use blame annotator:
svn blame failed on trunk/src/tmcsim/client/CADClient.java: ("Can't find a temporary directory: Internal error", 20014)

source: tmcsimulator/trunk/src/tmcsim/client/CADClient.java @ 361

Revision 361, 19.5 KB checked in by jdalbey, 7 years ago (diff)

modify CADClient AssignedIncidents?.java to fix defect #142. Also fix minor typos in full_script_2016.xml

RevLine 
1package tmcsim.client;
2
3import java.awt.event.WindowEvent;
4import java.awt.event.WindowListener;
5import java.io.FileInputStream;
6import java.io.FileOutputStream;
7import java.io.IOException;
8import java.rmi.Naming;
9import java.rmi.RemoteException;
10import java.rmi.server.UnicastRemoteObject;
11import java.util.Properties;
12import java.util.Vector;
13import java.util.logging.Level;
14import java.util.logging.Logger;
15
16import javax.swing.JFrame;
17import javax.swing.JOptionPane;
18import javax.swing.JWindow;
19import javax.swing.UIManager;
20
21import tmcsim.client.cadclientgui.CADClientGUI;
22import tmcsim.client.cadclientgui.CardfileReader;
23import tmcsim.client.cadclientgui.GUIScriptReader;
24import tmcsim.client.cadclientgui.data.CADData;
25import tmcsim.client.cadclientgui.screens.Login;
26import tmcsim.client.cadclientgui.screens.ScreenManager;
27import tmcsim.common.CADEnums;
28import tmcsim.common.SimulationException;
29import tmcsim.interfaces.CADClientInterface;
30import tmcsim.interfaces.CoordinatorInterface;
31
32/**
33 * CADClient is the main class for the CAD Client application. The main method
34 * instantiates an instance of the CADClient object with the default properties
35 * file "..\config\CADClient.properties" or the first argument fom the command
36 * line invocation. Properties data values are used to bind socket communication
37 * between the CAD Client and the CAD Simulator. The CADClientModel object is
38 * instantiated and the CAD Client registers itself with the CAD Simulator.
39 * Finally, the CADClientView is initialized, the model-view and observer
40 * relationships are established, and the view is shown.<br>
41 * <br>
42 * The properties file contains the following data: <br>
43 * <code>
44 * -----------------------------------------------------------------------------<br>
45 * Host Name     The host name where the CAD Simulator is located.<br>
46 * Port Number   The port number that the CAD Simulator is bound on.<br>
47 * CAD Position  The integer (>= 0) position for this CAD Client.<br>
48 * CAD User ID   The unique user id for this CAD Client.<br>
49 * Error File    Filename of error logging file.<br>
50 * -----------------------------------------------------------------------------<br>
51 * Example File: <br>
52 * CADSimulatorHost       = localhost<br>
53 * CADSimulatorSocketPort = 4444<br>
54 * CADPosition = 1 <br>
55 * CADUserID   = A12345<br>
56 * ErrorFile   = cad_client_err.txt<br>
57 * </code>
58 *
59 * @author Matthew Cechini (mcechini@calpoly.edu)
60 * @version $Date: 2009/04/17 16:27:47 $ $Revision: 1.8 $
61 */
62
63public class CADClient extends UnicastRemoteObject implements
64        CADClientInterface {
65
66    /** Error logger. */
67    private static Logger cadClientLogger = Logger.getLogger("tmcsim.client");
68
69    /**
70     * Enumeration containing properties name values. See CADClient class
71     * description for more information.
72     *
73     * @author Matthew Cechini
74     * @see CADClient
75     */
76    private static enum PROPERTIES {
77        CAD_SIM_HOST("CADSimulatorHost"), CAD_SIM_PORT("CADSimulatorSocketPort"), CAD_RMI_PORT(
78                "CADRmiPort"), CLIENT_CAD_POS("CADPosition"), CLIENT_USER_ID(
79                "CADUserID"), KEYBOARD_TYPE("KeyboardType"), DISPLAY_TYPE(
80                "DisplayType");
81
82        public String name;
83
84        private PROPERTIES(String n) {
85            name = n;
86        }
87    }
88
89    /**
90     * CADClientSocket Object to handle socket communication between the Client
91     * and CAD Simulator.
92     */
93    private CADClientSocket theClientSocket;
94
95    /** Instance of the CADClientModel. */
96    private CADClientModel theClientScreenModel;
97
98    /** Instance of the CADClientView. */
99    private CADClientView theClientScreenView;
100
101    /**
102     * Instance of the CADCLientGUI Replaces CADClientView
103     */
104    private CADClientGUI theClientGUI;
105
106    /** Properties object for the CADClient class. */
107    private Properties cadClientProp;
108
109    /** RMI interface for communication with the remote Coordinator. */
110    private static CoordinatorInterface theCoorInt;
111
112    /** reference to itself to be used for disconnecting from CADSimulator */
113    private CADClientInterface client = this;
114
115    private static final String CONFIG_FILE_NAME = "cad_client_config.properties";
116   
117    /**
118     * Constructor. Initialize data from parsed properties file. Create a socket
119     * connection to the CADSimulator. The ClientScreenModel is initialized with
120     * the input and output I/O streams for socket communication. The
121     * ClientScreenModel registers with the CAD Simulator, using CAD position
122     * and userID read in from the properties file. The ClientScreenView is then
123     * created and initialized and set as an observer of the model.
124     *
125     * A thread is created with the runnable ClientScreenModel and is started.
126     * When this thread is no longer alive, or the ClientScrenView and
127     * CADClientSocket are closed. The program then exits.
128     *
129     * @param propertiesFile
130     *            File path (absolute or relative) to the properties file
131     *            containing configuration data.
132     */
133    public CADClient(String propertiesFile) throws SimulationException,
134            RemoteException {
135        if (!verifyProperties(propertiesFile))
136            System.exit(0);
137
138        connect(cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name).trim(),
139                cadClientProp.getProperty(PROPERTIES.CAD_RMI_PORT.name).trim());
140
141        // Instantiate the Socket and Model Objects.
142        theClientSocket = new CADClientSocket(cadClientProp.getProperty(
143                PROPERTIES.CAD_SIM_HOST.name).trim(),
144                Integer.parseInt(cadClientProp.getProperty(
145                        PROPERTIES.CAD_SIM_PORT.name).trim()));
146        theClientScreenModel = new CADClientModel();
147        theClientScreenModel.initializeScreen(theClientSocket.getInputStream(),
148                theClientSocket.getOutputStream());
149
150        // Register this CAD Client with the Simulation Manager
151        theClientScreenModel.register(Integer.parseInt(cadClientProp
152                .getProperty(PROPERTIES.CLIENT_CAD_POS.name)), cadClientProp
153                .getProperty(PROPERTIES.CLIENT_USER_ID.name));
154
155        // Instantiate the CADScreenView and set up the model-view observer
156        // relationship.
157        theClientScreenView = new CADClientView(theClientScreenModel);
158        theClientScreenView.setVisible(false);
159
160        // TODO: set up model-view relationship similar to ClientView and
161        // ScreenView
162        // Can repurpose the old model, but may be better to copy over and
163        // modify in parallel
164        // This is required to perform powerline commands on the data
165        theClientGUI = new CADClientGUI();
166
167        // Each screen of the UI should have a reference to either it's parent
168        // object or the main client
169        // This ensures they all have access to each other and the data model
170        theClientGUI.screen = new ScreenManager(theCoorInt);
171        theClientGUI.login = new Login();
172        theClientGUI.client = this;
173
174        // setup keyboard settings for CAD Client
175        if (cadClientProp.getProperty(PROPERTIES.KEYBOARD_TYPE.name).trim()
176                .equals("CAD")) {
177            CADEnums.CAD_KEYS.setupCADKeyboard();
178        }
179        // STD
180        else {
181            CADEnums.CAD_KEYS.setupStandardKeyboard();
182        }
183
184        theClientScreenModel.addObserver(theClientScreenView);
185
186        // Initialize the display
187        if (cadClientProp.getProperty(PROPERTIES.DISPLAY_TYPE.name).equals(
188                "FULL_SCREEN")) {
189
190            theClientScreenView.addWindowListener(new WindowListener() {
191                public void windowClosed(WindowEvent e) {
192                }
193
194                public void windowOpened(WindowEvent e) {
195                }
196
197                public void windowIconified(WindowEvent e) {
198                }
199
200                public void windowDeiconified(WindowEvent e) {
201                }
202
203                public void windowActivated(WindowEvent e) {
204                }
205
206                public void windowDeactivated(WindowEvent e) {
207                }
208
209                public void windowClosing(WindowEvent e) {
210
211                    try {
212                        theClientSocket.closeSocket();
213                    } catch (SimulationException se) {
214                    }
215
216                    System.exit(0);
217                }
218            });
219
220            theClientScreenView.initWindow();
221            theClientScreenView.setVisible(false);
222        } else {
223            JFrame cadFrame = new JFrame("CAD Client");
224            cadFrame.add(theClientScreenView.initBox());
225            cadFrame.setSize(800, 600);
226
227            cadFrame.addWindowListener(new WindowListener() {
228                public void windowClosed(WindowEvent e) {
229                }
230
231                public void windowOpened(WindowEvent e) {
232                }
233
234                public void windowIconified(WindowEvent e) {
235                }
236
237                public void windowDeiconified(WindowEvent e) {
238                }
239
240                public void windowActivated(WindowEvent e) {
241                }
242
243                public void windowDeactivated(WindowEvent e) {
244                }
245
246                public void windowClosing(WindowEvent e) {
247
248                    try {
249                        theClientSocket.closeSocket();
250                    } catch (SimulationException se) {
251                    }
252
253                    System.exit(0);
254                }
255            });
256
257            cadFrame.setVisible(true);
258        }
259
260        // Create the CAD Client thread to run the CADClientModel Object.
261        Thread clientThread = new Thread(theClientScreenModel);
262       
263        // Log that everything started okay
264        clientThread.start();
265            cadClientLogger.logp(Level.INFO, "CAD Client",
266                    "Constructor",
267                    "Initialization complete.");
268
269        ensureProperShutdown();
270       
271       
272    }
273
274    /**
275     * Connect to the Coordinator's RMI object, and register this object for
276     * callback with the Coordinator.
277     *
278     * @param hostname
279     *            Host name of the CAD Simulator.
280     * @param portNumber
281     *            Port number of the CAD Simulator RMI communication.
282     * @throws SimulationException
283     *             if there is an error creating the RMI connection.
284     */
285    protected void connect(String hostname, String portNumber)
286            throws SimulationException {
287
288        String coorIntURL = "";
289
290        try {
291            coorIntURL = "rmi://" + hostname + ":" + portNumber
292                    + "/coordinator";
293            theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
294            theCoorInt.registerForCallback(this);
295        } catch (Exception e) {
296            throw new SimulationException(SimulationException.CAD_SIM_CONNECT,hostname,
297                    e);
298        }
299    }
300
301    /**
302     * This method verifies that the CAD Simulator Host and Port values are not
303     * null. Also, if a CAD Position or User ID do not exist in the properties
304     * file, the user is prompted to enter values. These values are written to
305     * the properties file. If the user cancels the process of entering these
306     * values, the verification fails.
307     *
308     * @param propertiesFile
309     *            File path (absolute or relative) to the properties file
310     *            containing configuration data.
311     * @return True if the properties file is valid, false if not.
312     * @throws SimulationException
313     *             if there is an exception in verifying the properties file, or
314     *             if the user cancels input.
315     */
316    private boolean verifyProperties(String propertiesFile)
317            throws SimulationException {
318
319        // Load the properties file.
320        try {
321            cadClientProp = new Properties();
322            cadClientProp.load(new FileInputStream(propertiesFile));
323        } catch (Exception e) {
324            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
325                    "Constructor", "Exception in reading properties file.", e);
326
327            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
328                    e);
329        }
330       
331
332        // Ensure that the properties file does not have null values for the
333        // CAD Simulator's connection information.
334        if (cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name) == null
335                || cadClientProp.getProperty(PROPERTIES.CAD_SIM_PORT.name) == null) {
336            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
337                    "Constructor", "Null value in properties file.");
338            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
339        }
340
341        try {
342            // If the properties file does not specify a CAD position, prompt
343            // the
344            // user to select one. If the user selects a position, write the
345            // new properties values to the file. If the user cancels, else
346            // throw an exception.
347            if (cadClientProp.getProperty(PROPERTIES.CLIENT_CAD_POS.name) == null) {
348                if (getCADPosition())
349                    cadClientProp.store(new FileOutputStream(propertiesFile),
350                            "");
351                else
352                    throw new SimulationException(
353                            SimulationException.INITIALIZE_ERROR);
354            }
355
356            // If the properties file does not specifiy a CAD User ID, prompt
357            // the
358            // user to enter a value. If the user enters a valid ID, write the
359            // new properties values to the file. If the user cancels, else
360            // throw an exception.
361            if (cadClientProp.getProperty(PROPERTIES.CLIENT_USER_ID.name) == null) {
362                if (getUserID())
363                    cadClientProp.store(new FileOutputStream(propertiesFile),
364                            "");
365                else
366                    throw new SimulationException(
367                            SimulationException.INITIALIZE_ERROR);
368            }
369        } catch (IOException ioe) {
370            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
371                    "Constructor",
372                    "Exception in writing to the properties file.");
373            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
374        }
375
376        // Ensure that the properties file has a valid display type
377        if (cadClientProp.getProperty(PROPERTIES.DISPLAY_TYPE.name) == null
378                || (!cadClientProp.getProperty(PROPERTIES.DISPLAY_TYPE.name)
379                        .equals("FULL_SCREEN") && !cadClientProp.getProperty(
380                        PROPERTIES.DISPLAY_TYPE.name).equals("FRAME"))) {
381            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
382                    "Constructor", "Invalid display type.");
383            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
384        }
385
386        return true;
387    }
388
389    /**
390     * This method prompts the user to select a value for the CAD position. If
391     * the user cancels the method returns false, else the Properties object is
392     * updated and true is returned.
393     *
394     * @return True if the user successfully selected a CAD position, false if
395     *         not.
396     */
397    private boolean getCADPosition() {
398
399        Vector<Integer> positions = new Vector<Integer>();
400        for (int i = 0; i < 10; i++)
401            positions.add(i);
402
403        Object cadPos = null;
404
405        while (true) {
406            cadPos = JOptionPane.showInputDialog(null,
407                    "Please assign this workstation a CAD position number.",
408                    "CAD Position Asignment", JOptionPane.QUESTION_MESSAGE,
409                    null, positions.toArray(), positions.get(0));
410
411            // If the user pressed cancel, confirm the exit and return false.
412            if (cadPos == null) {
413                if (JOptionPane
414                        .showConfirmDialog(
415                                null,
416                                "CAD Client cannot load until a valid CAD "
417                                        + "position has been selected.  Do you wish to "
418                                        + "cancel loading the CAD Client?",
419                                "Confirm Exit", JOptionPane.YES_NO_OPTION,
420                                JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION)
421                    return false;
422            }
423            // Else the user selected a CAD position, exit the loop.
424            else {
425                break;
426            }
427        }
428
429        cadClientProp.setProperty(PROPERTIES.CLIENT_CAD_POS.name,
430                cadPos.toString());
431        return true;
432    }
433
434    /**
435     * This method prompts the user to enter a 5-character User ID. If the user
436     * cancels the method returns false, else the Properties object is updated
437     * and true is returned.
438     *
439     * @return True if the user successfully selected a CAD position, false if
440     *         not.
441     */
442    private boolean getUserID() {
443        String cadUID = null;
444
445        while (true) {
446            cadUID = JOptionPane.showInputDialog(null,
447                    "Please assign this workstation a 6-character CAD "
448                            + "User ID.", "CAD User ID Asignment",
449                    JOptionPane.QUESTION_MESSAGE);
450
451            // /If the user pressed cancel, confirm the exit and return false.
452            if (cadUID == null) {
453                if (JOptionPane.showConfirmDialog(null,
454                        "CAD Client cannot load until a valid User ID "
455                                + "has been entered.  Do you wish to "
456                                + "cancel loading the CAD Client?",
457                        "Confirm Exit", JOptionPane.YES_NO_OPTION,
458                        JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION)
459                    return false;
460            }
461            // If the user does not enter a valid User ID, notify and reprompt.
462            else if (cadUID.length() != 6) {
463                JOptionPane.showMessageDialog(null,
464                        "The User ID must be 6 characters.", "Invalid User ID",
465                        JOptionPane.WARNING_MESSAGE);
466            }
467            // Else the user entered a valid value, exit the loop.
468            else {
469                break;
470            }
471        }
472
473        cadClientProp.setProperty(PROPERTIES.CLIENT_USER_ID.name, cadUID);
474        return true;
475    }
476
477    /**
478     * Construct the CADClient with the properties file path, either from the
479     * command line arguments or default.
480     *
481     * @param args
482     *            Command line arguments.
483     */
484    public static void main(String[] args) {
485        if(System.getProperty("CONFIG_DIR") == null){
486                System.setProperty("CONFIG_DIR", "config");
487        }
488
489        try {
490            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
491            new CADClient(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME);
492         
493        } catch (Exception e) {
494            cadClientLogger.logp(Level.SEVERE, "SimulationManager", "Main",
495                    "Error initializing application.");
496
497            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
498                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
499
500            System.exit(-1);
501        }
502
503    }
504
505    public void refresh() {
506        theClientGUI.screen.refreshScreens();
507    }
508
509    public void ensureProperShutdown() {
510        Runtime.getRuntime().addShutdownHook(new Thread() {
511            public void run() {
512                try {
513                    theCoorInt.unregisterForCallback(client);
514                } catch (RemoteException e) {
515                    e.printStackTrace();
516                }
517            }
518        });
519    }
520
521}
Note: See TracBrowser for help on using the repository browser.