Project : FlightSystem
This project developed in java leads us to
realize a flight reservation system in order to emulate databases containing
the structures for the flight and for the booking. These bases extend the List
interface and implements additional search’s methods.
Two interfaces provide an access to this
system. The first one reads and handles reservation request message from a
terminal. The arguments are then processed throw a middleware interface that
call the flight system methods. The second one, a Graphical User Interfaces
(GUI) application using Swing Java Foundation Classes (JFC), offers a simpler
access to the systems.
Abstract.. 1
Summary.. 1
Introduction.. 3
I. Flight
System GUI 3
A. CustomDialog. 3
B. Panels. 4
1) Implementation. 4
2) MainPanel 5
3) CreatePanel 5
4) ReservePanel 6
5) CancelPanel 6
6) SelectPanel 7
7) FlightsPanel 7
II. New
features.. 8
A. The “flights” instruction. 8
B. Solution to store the data. 9
1) Reverse construction. 9
2) Serialization of the data. 10
3) XML format 10
4) Serializable interface. 10
C. The
class Store.. 10
D. The
class Reload.. 11
Conclusion.. 11
Welcome back to Java Airline.
As promise, a new version is being released. This one offers again more
features and functionalities and an advance user interface. Indeed, graphical dialogs
as been designs to access the database. This application will guide you all
over the treatment of your application. The new functionalities developed offer
you to store and to reload the content of the database. During the next few
minute, you may learn how to use common widget (Dialog, button, table …). You
may also have more example of the design by abstraction. We thank you to choose
again our company for your next destination and we wish you a good flight.
A user can execute the program by executing
in a console the fallowing statement:
%java -classpath FlightSystem.jar
FlightSystemGUI
The main class FlightSystemGUI will
then creates a new instance of the principal dialog.
Mode mode= new CustomDialog (Mode.DEBUG);
mode.process
();
The GUI interface is based on modal Dialog.
The class CustomDialog, that inherits the JDialog JFC, offers the general methods to manage the FlightSystem. A label
and two panels compose this dialog: ActionPanel and FootPanel (refer to
CustomDialog in Figure 1.1). The ActionPanel is one of the six classes
inherited from the Panels abstract class. FootPanel is a private inner class of CustomDialog that contains two JButtons
validating or aborting the action. The title label and the ID of the ActionPanel may be passed in parameter when a new CustomDialog is
constructed. This approach reduces the number of implementation of Dialog used.
This CustomDialog provides the common methods to encapsulate the actions. In so
doing, the addition of functionality would only require a new Panels class
to be constructed. The custom dialog also provides two methods to inform the
user when an error occurs.
static public void alert (Exception exception) { JOptionPane.showMessageDialog
(null, exception.getMessage (),...); if (VerboseMode == DEBUG) exception.printStackTrace (); }
This class is related to the action the
user wants to perform. Therefore, it extends the Action interface and implements
the JPanel class. This class behaves as the Functions class.
(Refer to the first assignment Chap. I.B3)
The general design used to implement these
panels was inspired from the example 8.13 of the Object-Oriented Software
Development Using Java book (ref 1).The layout methods doLayout(), getPreferedSize()
and getMinimumSize() inherit from JPanel.
When the user selects one of the possible
actions, a switch statement (1) handles the choice. According to command, a
JfileChooser Dialog is opened (2) or a new CustomDialog is instantiated (3) with
the corresponding Panel. In that case, the action and the title are passed to
the constructor of CustomDialog. If the action to perform does not require a new CustomDialog (2), the function is simply executed there. The result is then appends
to the textArea (8). Otherwise, the panel corresponding to the action is
instantiated (4). A click on the valid JButton executes one of the
classes inherited by Panels (5). The different input values are collected from
the form and then are transmitted to their related Functions class (6). At that
moment, the result string is send back to the JPanel (7) is appended to the textArea (8).
The MainPanel is the default panel opened
by CustomDialog. Its functions are to redirect the user in function of the action
he wants to perform. Furthermore, it displays in resultTextArea some
historical information about the actions requested. The actionComboBox lists all the possible action. More actions are enabling when the
flight and / or list are not empty.
Three JTextField and their related Jlabel
compose this panel.
public String execute (String[] unUsed) { Action action = new Create(); String arg[] = { nameInput.getText(), rowsInput.getText(), rowLengthInput.getText() }; return action.execute(arg); }
Once a flight created, this dialog will appear when
the main window is closed. This Dialog is implemented thanks to the JOptionPane
JFC that offers a friendly way to created input dialog.
When the ReservePanel is
instantiated, the init() method fills the flightSelect
with the available flights. To obtain this list, the
method getFlightList ()
is invoked on FlightSystem. The user is then able to
enter the name of the passenger he want to book for. A click on the addButton
appends the name in the nameSelect. As soon as validated, the String array arg is filled with
the list of value contained in nameSelect . After that, this array is proceed by the Reserve class
(inherits Action Interface).
The identifyButton fills the passengerList with the person’s name corresponding to a booking number.
Therefore, the method Identify(bookingNumber : int) :
Vector is invoked on FlightSystem. If the data exceed
the size of the passengerList, this latter is scrolled. The user is then able to select one or
more person from that list. The Person (s) selected are execute by
the Reserve class.
The select panel provides advance search functionality
to the Flight System. Since this panel does not alter the FlightSystem, the execute() method is empty. The init method fills the flightSelect and the bookingSelect with respectively the available flights and booking number. On a click
on the searchButton, a Profile object is instantiated with the corresponding to the input values.
This profile is next send to the search method on FlightSystem. The value returned
is a vector of person object. The different values (Name, person, booking
number and seat) are extracted from each person. According to the result value,
a multi-dimension array is created. This array constitutes the bookingTable.
The implementation of FlightsPanel is
comparable to SelectPanel.
The improvement of the reservation system has
to contain the three new instructions:
flight: list
the created flights
store: store
the database into a file
reload: load
the saved data.
During the conception of the previous
version FlightSystem, we prevented any extension of this class. Therefore, we declared
the class final and its constructor private. To preserve these properties, the
solution to override the class FlightSystem with a class FlightSystemTwo was not retained. Indeed, the previous version already contains the
methods needed to implement this new functionality. This one would just require
a new accessor on the FlightSystem class. To ensure that the modifications do not to avoid the good
working of the program, more tests have been performed.
We could discuss about whether or not the
prevention of the inheritance was a good design. This idea starts with the fact
that the singleton FlightSystem was the core of the program. Consequently, the
inner data as well as the instance have to be protected. Consequently, we made private
its constructor and the database (constitute by the inner class FlightList
and PersonList). The extension of the facilities was design to be done outside
this class; In the Functions class for example.
To add the instruction “flights” to
the system, we created a new Flights class that extends the abstract class Function. On call, the
flights object invokes the existing method getFlightList () in FlightSystem. This accessor returns a String array that contains the name of different
flights. Thus, to print out the flights’ list, the execute method appends
the list to a String.
String[] flightList = fs.getFlightList (); for (int i=0; i< flightList.length; i++) { retString += flightList[i] + " "; }
This command is available only if at least
one flight is registered. However, we only use this class with the command line
mode (related to FlightSystemUser). Indeed, it was more useful in the GUI application to invoke directly
the method getFlightList (). Finally, the instruction “flights” has been added to the
possible request in the command line mode (refer to the class Command
first assignment chapter I.B.2).
The first step in the development of the instructions
“store” and “reload” has been to look for the current possibility.
We have developed and tested two solutions:
A reverse construction
Serialization of the database
This first solution is the most practical one.
Indeed, we were already able to parse a file containing the “Request Command Messages”. The idea is to recreate the instructions (a set of “reserve”
and “create” instructions) from the database. For example, if the flight
SK234 with the dimension (4,
5) is present in the database, we could write into a
file the instruction:
create SK234 4 5.
In a similar way, if two passengers Lars
and Lys have booked on this
flight, the command would be:
reserve SK234 Lars Lys.
This solution could have been developed
without any modification into FlightSystem. It just require to create a new class Store extending
Functions. The inherited method execute() would required to instantiated
a PrintWriter object.
PrintWriter data = new PrintWriter (new BufferedWriter (
new FileWriter (fileName)));
After that, we collect all the flight
present in the database and for each of them, we save their name and their
dimension in the file.
String[] listFlight = fs.getFlightList (); for(int i = 0; i < listFlight.length; i++) { Flight flight = fs.selectFlight (listFlight[i]); String create = "create " + flight.getFlightName () + " " + flight.getDimension ().getRow () + " " + flight.getDimension ().getCol (); data.println (create); }
The reserve request may be done in a
similar way. This solution is working fine but the seat of the person would not
have been saved. If we load the file, the program attributes a new seat to the
passenger. In the other hand, this solution would gather the people that could
have been split after a cancel operation.
We could have used this solution because
the passenger dos not receive any information about his seat when he booked. So
that he will not worried if his seat has been changed. A trick could have been
to insert factice “cancel” commands to conserve the position of the passenger
but we did not retain this solution. Furthermore, the subject was quite clear;
the position of the person had to be saved.
Instead, we opted for the solution that
consists to serialize the data. Nevertheless, this solution requires the
addition of the following accessors into the FlightSystem class:
final public synchronized int reserve (Person person)
throws
Exception { return personList.add(person) ? 1 : 0; }
The +add(person:Object):boolean method in LinkedList has been overridden PersonList.
Note: We added
this method in the class FlightSystem because we wanted to keep the two inner linked lists in private but
we could have just change PersonList to public.
Now we are able to assert a person (with
all the corresponding information (flight, name, booking number and seat) into
the FlightSystem. Two main solutions could be used to serialize the data: One
of them is to export the flights and the persons into the XML format.
The XML language brings facilities to
manipulate and encapsulate the data. Some classes offer useful tools to encode
and decode XML tag. A significant property is that a file generated in this
format could be interpreted from another language. However, a parser has to be
created in order to extract and exploit the data.
The second solution is to serialize
directly the FlightSystem object. To do so, the classes Pos, Person, Flight and
of course FlightSystem have to implement the interface Serializable. The two
classes (Store and
reload) implement the method to respectively encode and
decode the data. Like the class Flight, they implement the abstract
class Functions and belong to the package “functions”.
Before to store the database the following conditions
are checked:
At least one flight exists in a database.
One only parameter is passed to the command
(the file’s name).
The file does not already exist.
The file can be created.
Then the method execute() can be
proceed:
FileOutputStream FileOut = new FileOutputStream (new
File (FileName)); ObjectOutputStream fout =
new ObjectOutputStream (FileOut); fout.writeObject (fs);
Before to reload the data the following
conditions are verified:
One only parameter is passed (the file’s
name)
The file exists
The file is readable
After that, if the command is valid, the FlightSystem
is deserialize:
FileInputStream FileIn new FileInputStream (FileName)); ObjectInputStream fin = new ObjectInputStream (FileIn); Object obj = fin.readObject (); if (obj instanceof FlightSystem) FlightSystem fsExtracted = (FlightSystem) obj;
Then we begin to assert the flights:
String[] listFlight = fsExtracted.getFlightList (); int decount = listFlight.length; for(int i = 0; i < listFlight.length; i++) { Flight flight = fsExtracted.selectFlight
(listFlight[i]).clone(); decount -= fs.create (flight)? 1 : 0; } if (decount != 0) throw new Exception ("Flight list partialy reloaded");
A similar method is employed to assert the
person.
The base is not clear before to reload instruction.
so that, the new flight and person are just append to the database. Of course,
the next booking number attributed is increase consequently. We could have
directly substitute the fs object by fsExtracted one but this solution would
not have verify the correctness of all the flight or person. Moreover we found
not suitable the solution that consist to modify the reference of a singleton.
This second project brings ameliorations to
the first FlightSystem. A new interface and some functionality have been added.
This improvement was not truly difficult to implement because the first system
was design to be extendable. However, we noticed some improvement that could
have been done previously. For example It would have been a good idea to create
an Exception class extending the RuntimeExecption. This would have allows to
handle more easily the error from the different methods. A possible improvement
for this new flight reservation system could be to allow the access to the
database from a network. A server/client socket-based system or Remote
Procedure Invocation could be suitable for this improvement.
Download documentation javadoc software (jar)
|