// $Id: ClientEngine.java,v 3.4 1998/12/10 18:57:23 rgb2u Exp $
/////////////////////////////////////////////////////////////////////
//
// File: ClientEngine.java
//
// Purpose: This describes the Client Engine class. The Client Engine is
// responsible for interfacing between the Client RMI module
// and the Client GUI module. It contains the logic that
// "runs" the client side of the simulation.
//
// Authors: rgb Rob Bartholet rgb2u@virginia.edu
// txe Travis Emmitt emmitt@cs.virginia.edu
//
// Modifications:
// 01-NOV-1998 rgb Initial Creation
// 02-NOV-1998 rgb Added version control header
// 02-NOV-1998 rgb Modified to conform to coding standards
// 04-NOV-1998 rgb Implemented PrintMessage so RMI can write to GUI
// rgb Removed rmi.Connect call from ClientEngine constructor
// rgb Any calls to rmi methods modified to catch RemoteException
// 04-NOV-1998 txe Debugging for integration
// 05-NOV-1998 rgb Updated ReceiveMap() to check state of finalized bit
// 06-NOV-1998 rgb Trivial change to move gui.Notify() before ClientRMI instantiation
// 06-NOV-1998 rgb In constructor, moved gui.Freeze() before ClientRMI instantiation
// rgb Changed all gui.Notify() to PrintMessage()
// 12-NOV-1998 rgb rgb Tested returned maps to ensure they belong to me
// rgb Implemented SetClientID()
// rgb Implemented ReceiveStats()
// 13-NOV-1998 rgb Changed connecting message to SetClientID
// 16-NOV-1998 rgb Added code to throw exceptions and catch exceptions
// 17-NOV-1998 rgb Fixed some compilation errors with signatures
// 18-NOV-1998 txe Improved exception handling
// 18-NOV-1998 rgb Cleaned up code
// 03-DEC-1998 rgb Added Quit()
// rgb Changed check on received map from final to editable
// 08-DEC-1998 rgb Added constructor to take address and port
// rgb wrapped ReceiveMap around Connect in new constructor
// 09-DEC-1998 rgb Removed deprecated constructor
// rgb Added unfreeze to SetClientID
//
// Todo:
//
/////////////////////////////////////////////////////////////////////
import java.rmi.*;
public class ClientEngine {
private ClientGUI client_gui; // used to call back ClientGUI
private ClientRMI client_rmi; // used to communicate with server
private Map map; // holds structure and state of model
private int module_id; // module number of this workstation
// constructor
// ClientEngine instantiated by ClientGui
// ClientEngine instantiates ClientRMI
public ClientEngine (ClientGUI gui, String address, String port) throws Exception {
if (gui == null) {
throw new NullException ("gui argument is nulll");
}
else {
client_gui = gui;
module_id = -1;
map = null;
client_gui.Freeze ();// don't allow user to modify the interface
client_rmi = new ClientRMI (this);
ReceiveMap (client_rmi.Connect (address, port), -1);
client_gui.Unfreeze (); // allow user to enter module ID
}
}
// allows client to set his own id
// subsequently passes id on to RMI
// if requested id set, returns true
// if requested id doesn't exist or already taken, returns false
public boolean SetClientID (int id) throws Exception {
client_gui.Freeze ();
PrintMessage ("Attempting to connect to server...");
module_id = id;
if (client_rmi.SetClientID (module_id)) {
PrintMessage ("Connected to server");
if (map != null && map.IsEditable () ) {
client_gui.Unfreeze ();
}
return (true);
}
module_id = -1;
client_gui.Unfreeze ();
return (false);
}
// receive map from server and send to gui
public void ReceiveMap (Map my_map, int my_module_id) throws Exception {
if (my_map == null) {
throw new NullException ("my_map argument is null");
}
else {
map = my_map;
if (module_id != my_module_id) {
throw new EqualityException ("unexpected module_id");
}
client_gui.DisplayMap (map, module_id);
// if map is stabilized
if ( my_map.IsEditable () ) {
client_gui.Unfreeze();// allow user to use the interface
}
}
}
// receive stats from server and send to gui
public void ReceiveStats (Stats my_stats, int my_module_id) throws Exception {
if (my_stats == null) {
throw new NullException ("my_stats is null");
}
else {
if (module_id != my_module_id) {
throw new EqualityException ("unexpected module_id");
}
client_gui.DisplayStats (my_stats);
}
}
// user clicks on node
// toggle node and redisplay map
public void NodeClicked (int my_module_id, int node_id) throws Exception {
if (my_module_id != module_id) {// not in our module
PrintMessage ("Can't toggle a node from another module");
}
else {
map.ToggleNode (my_module_id, node_id);
client_gui.DisplayMap (map, module_id);
}
}
// user done inputting changes
// send changes to server
public void DoneClicked () throws Exception {
Module my_module = null;
PrintMessage ("Sending changes to server...");
client_gui.Freeze ();// freeze interface so user can't use it
my_module = map.GetModule (module_id);
client_rmi.SendChanges (my_module);
}
// RMI wants to print a message to the GUI output
// receive string from RMI, pass on to GUI
public void PrintMessage (String s) {
client_gui.Notify (s);
}
// Demon user decides to shut down system
// freeze display and print shut down message
public void Shutdown () {
client_gui.Freeze ();
PrintMessage ("System shut down by server");
}
// Method for RMI to pass exceptions to GUI for display
public void Error (Exception e) {
client_gui.Error (e);
}
// method for gui to call when applet is destroyed
public void Quit () throws Exception {
client_rmi.Quit ();
}
}