This report shows the total number of points awarded for each section. The maximum number of points is 400, to pass you need a score of 320.
Section Max Actual Points Points General Con: 100 90 Documentation: 70 65 OOD: 30 30 GUI: 40 31 Locking: 80 80 Data Store: 40 40 Network Server: 40 30 Total: 400 366
I am very happy, it is more than I expected.
I have been lurking this forum for a long time and it has been very helpful to me, along with Max Habib's book. It has been pretty tough for me since I didn't really know many of the technologies and of the patterns. Don't ask me how long it took
I'll post details about my solution this weekend since right now I am very busy at work
And then I am going to PARTY !!
[ March 16, 2005: Message edited by: Diego Amicabile ] [ March 16, 2005: Message edited by: Diego Amicabile ]
First, I have a class Record around the String instances which are used by the DBMain methods and represents a occupancy. Using a wrapper is a simple way to remember and manage the relevant information associated with a occupancy.
The class Data acts as the facade to the back-end tier. The class Data is the back end's backbone. There are several instances of Data, one for each client. This is the easiest way I found out to be able to tell whether a record has been locked by the current Data instance or not. I just associate a record with a locker (a Data instance). The Data class methods do not lock or unlock a record. Lock / unlock methods in the Data class are called by the DataFacade, the wrapper around Data. The lock / unlock / isLocked methods delegate to the LockManager, delete / update / read delegate record access to the class RecordManager. Update and delete will throw an exception if you are trying to perform the operation on a record which is not locked. The create method is synchronized on the Data class, so that only one thread is allowed to try and create a new record at any given time.
LockManager helps implement the lock , unlock and isLocked methods in the Data class. Internally, in lock manager, that happens through a Map. The Map instance maps an Integer (the record number) to the Data object which is holding the abstract lock (locker), if there is any. LockManager is a singleton and is referenced by the Data class.
The RecordManager singleton manages access to the file. Its methods are synchronized. RecordManager contains two caches. One cache (recordCache) contains the records which are read from the file, the other the list of currently deleted records.
The DataFacade interface is the interface which exposes business methods to the client
The DataFacade interface provides the business methods that the gui needs at this stage. The client needs to book, unbook, and search for records. The gui should not deal with locking and data consistency issues, this is done inside of the DataFacade implementations.
The DataAdapter is a local implementation of DataFacade. The RemoteDataFacade interface extends Remote and DataFacade The RemoteDataFacadeImpl class extends DataAdapter, and implements RemoteDataFacade. It is exported through UnicastRemoteObject.export. I chose to make RemoteDataFacadeImpl a subclass of DataAdapter because it "is" a remote DataAdapter.
The RemoteFacadePool is the other Remote object. It manages a pool of RemoteDataFacade object. A client talks to the RemoteFacadePool on the server and tries to get a RemoteDataFacadeImpl from its virtual pool. If none is available, a TooManyConnectionsException will be thrown.
DataFacadeBridge hides the connection and the implementation details of DataFacade, so that the GuiController does not need to know if it is running locally or connecting remotely. It just asks the DataFacadeBridge to give him an instance of DataFacade.
GuiController works as a mediator between the view, the bridge to the DataFacade implementation and the model. RoomTableModel is the model containing the actual data about the occupancies.
View is the proxy to the View. View is implemented by MainWindow. View exposes the methods that the controller needs to interact with the user. Having View as an interface provides flexibility if the Gui ever needs to be reprogrammed.
MainWindow implements View as a JFrame with a Menu, a ToolBar, and four panels. Two JSplitPanes are used to separate the panels.
The MainWindow's constructor is passed the following parameters : - The title - The TableModel for the JTable - An ActionGroup instance, which is a wrapper class containing the Actions and the Listeners that have to be associated with the widgets inside MainWindow
All actions and listeners have a reference to the controller. The GuiController has a reference to a DataFacadeBridge, to a View and to a RoomTableModel. The View does not know about the controller.