ReservationController.java
1 |
|
2 |
import java.util.HashSet; |
3 |
import java.util.Date; |
4 |
|
5 |
/** |
6 |
* Controller class for the Reservations of this program. |
7 |
* Since this program handles a youth hostel, it's imperative that it holds a |
8 |
* number of Reservations. |
9 |
* |
10 |
* ReservationController takes the responsibility of handling the addition, |
11 |
* cancelling, editing, ... of Reservations, and the related tasks inherent to |
12 |
* these responsibilities, such as reserving beds, generating IDs, ... |
13 |
* @author Maarten Vangeneugden - 1438256 |
14 |
*/ |
15 |
public class ReservationController { |
16 |
|
17 |
/* Rationale: |
18 |
* Normally I'd put this as an interface (Set), but an interface does not |
19 |
* inherit from Object, and thus, does not provide clone(). This is |
20 |
* necessary, because otherwise, there's no point in having private |
21 |
* members. |
22 |
*/ |
23 |
private HashSet<Reservation> reservations; // Holds all Reservations |
24 |
private RoomController roomController; |
25 |
|
26 |
/** |
27 |
* Creates the ReservationController. |
28 |
* @param roomController The RoomController of the system. |
29 |
* @pre roomController mustn't be null. |
30 |
* @throws NullPointerException if roomController is null. |
31 |
*/ |
32 |
public ReservationController(RoomController roomController) { |
33 |
if(roomController == null) |
34 |
throw new NullPointerException("roomController mustn't be a null pointer."); |
35 |
this.reservations = new HashSet<>(); |
36 |
this.roomController = roomController; |
37 |
} |
38 |
|
39 |
/** |
40 |
* Returns a copy of all Reservations. |
41 |
* Emphasis on "copy"; There is no setReservations() for a reason, using |
42 |
* this to edit the pointer variable would omit the use of 'private'. |
43 |
* @return A verbatim copy of all Reservations. |
44 |
*/ |
45 |
@SuppressWarnings("unchecked") |
46 |
public Set<Reservation> getReservations() { |
47 |
return (HashSet<Reservation>)this.reservations.clone(); |
48 |
} |
49 |
|
50 |
/** |
51 |
* Generates a unique ID for a new Reservation. |
52 |
* This method is to be called when a new Reservation is to be stored. |
53 |
* As every Reservation carries an ID, this method searches for a unique |
54 |
* one, and returns it. |
55 |
* @return An integer, different from all other stored Reservation IDs. |
56 |
*/ |
57 |
public int generateReservationID() { |
58 |
/* Small optimization idea: |
59 |
* Instead of starting from 0, and incrementing until it's unique, it |
60 |
* will take the amount of stored Reservations, and test that as an ID. |
61 |
* This may still overlap (by removing an older Reservation), but may be |
62 |
* much faster. Consider implemting and testing for effectiveness if |
63 |
* generating an ID takes too long. |
64 |
*/ |
65 |
int ID = 0; |
66 |
boolean isUnique = false; |
67 |
do { |
68 |
ID++; |
69 |
isUnique = true; |
70 |
for(Reservation reservation: this.reservations) { |
71 |
if(ID == reservation.getReservationID()) { |
72 |
isUnique = false; |
73 |
} |
74 |
} |
75 |
} while(!isUnique); |
76 |
// Test: |
77 |
for(Reservation reservation: this.reservations) { |
78 |
assert reservation.getReservationID() != ID : "Duplicate ID generated!"; |
79 |
} |
80 |
return ID; |
81 |
} |
82 |
|
83 |
/** |
84 |
* Check if Reservation can be made. |
85 |
* Call this method whenever you're planning on adding a new Reservation. It |
86 |
* will check the provided requirements (Room facilities, for example), and |
87 |
* return whether this Reservation can continue. |
88 |
* |
89 |
* This method is deprecated. Use RoomController directly. |
90 |
* @see RoomController.getQualifiedRoom |
91 |
* @param reservation The Reservation to check for possible addition. |
92 |
* @pre reservation mustn't be null. |
93 |
* @throws NullPointerException if reservation is null. |
94 |
* @return True if reservation can be added, False otherwise. |
95 |
*/ |
96 |
@Deprecated |
97 |
public boolean checkReservation(Reservation reservation) { |
98 |
if(reservation == null) { |
99 |
throw new NullPointerException("reservation was a null pointer."); |
100 |
} |
101 |
if(this.roomController.getQualifiedRoom(reservation) == null) { |
102 |
return false; |
103 |
} |
104 |
return true; |
105 |
} |
106 |
|
107 |
/** |
108 |
* Adds and confirms the reservation. |
109 |
* By calling this method, the given reservation will be stored in the |
110 |
* system, and the given room will be filled. |
111 |
* You are to collect the necessary data, and assure yourself that all |
112 |
* preconditions have been met. |
113 |
* |
114 |
* The best way to accomplish this, is to only send 'sterile' Reservations |
115 |
* as the first parameter. That is: Reservations without reserved Beds, |
116 |
* without prior addition to the active Reservations, etc. |
117 |
* NOTE: You must check for yourself if the Reservation can take place in |
118 |
* this Room! If there are not enough Beds available, an exception will be |
119 |
* thrown. |
120 |
* @param reservation The Reservation to add. |
121 |
* @param room The Room in which the people will reside. |
122 |
* @pre room must have enough empty beds. |
123 |
* @pre room must accomodate the Reservation's requirements. |
124 |
* @pre No parameter must be null. |
125 |
* @pre reservation mustn't already be stored in the active Reservations. |
126 |
* @post reservation is stored in the active Reservations. |
127 |
* @post The Beds in the provided Room are reserved for the Reservation's |
128 |
* period. |
129 |
* @throws IllegalArgumentException if the given Room can't fulfill the |
130 |
* requirements of the Reservation, or occupants is less than 1. |
131 |
* @throws NullPointerException if any parameter is a null pointer. |
132 |
*/ |
133 |
public void addReservation(Reservation reservation, Room room) { |
134 |
// Contract validation. Null pointers are implicitely checked by calling |
135 |
// methods. |
136 |
if(!this.roomController.getQualifiedRooms(reservation).contains(room)) |
137 |
throw new IllegalArgumentException("The given Room cannot meet all requirements of the Reservation."); |
138 |
if(this.getReservations().contains(reservation)) |
139 |
throw new IllegalArgumentException("The given Reservation was already included in the active Reservations."); |
140 |
// Contract validated |
141 |
// Acquire unique ID: |
142 |
reservation.setReservationID(this.generateReservationID()); |
143 |
// Fill the required beds |
144 |
Bed[] beds = room.getEmptyBeds(reservation.getBeginDate(), reservation.getEndDate()).toArray(new Bed[1]); |
145 |
Set<Bed> reservedBeds = new HashSet<>(); |
146 |
for(int i=0; i<reservation.getPeople(); i++) { |
147 |
beds[i].reservePeriod(reservation.getBeginDate(), reservation.getEndDate()); |
148 |
reservedBeds.add(beds[i]); |
149 |
} |
150 |
reservation.setReservedBeds(reservedBeds); |
151 |
// Finally, add the Reservation to the system |
152 |
this.reservations.add(reservation); |
153 |
} |
154 |
|
155 |
/** |
156 |
* Cancels and removes the given Reservation. |
157 |
* If you want to remove a Reservation, use this method, and provide the |
158 |
* Reservation up for removal. |
159 |
* This method will take care of related actions, such as releasing Beds. |
160 |
* @param reservation The Reservation to be removed. |
161 |
* @pre reservation mustn't be null. |
162 |
* @pre reservation must be contained in the active Reservations. |
163 |
* @post The Reservation is removed from the active Reservations. |
164 |
* @post The Beds, previously reserved for this Reservation, are now |
165 |
* released, and can be reserved for another Reservation. |
166 |
* @throws NullPointerException if reservation is a null pointer. |
167 |
* @throws IllegalArgumentException if reservation is not contained in the |
168 |
* active Reservations. |
169 |
*/ |
170 |
public void cancelReservation(Reservation reservation) { |
171 |
// Contract validation |
172 |
if(!this.getReservations().contains(reservation)) { |
173 |
throw new IllegalArgumentException("The given Reservation was not contained in the active Reservations."); |
174 |
} |
175 |
if(reservation == null) { |
176 |
throw new NullPointerException(); |
177 |
} |
178 |
// Contract validated, execute method |
179 |
this.reservations.remove(reservation); // Remove from active Reservations |
180 |
for(Bed bed: reservation.getReservedBeds()) { // Release reserved Beds |
181 |
bed.removeReservationPeriod(reservation.getBeginDate(), reservation.getEndDate()); |
182 |
} |
183 |
// Asserting post conditions are met |
184 |
assert !this.getReservations().contains(reservation) : "The reservation is still part of the active Reservations."; |
185 |
for(Bed bed: reservation.getReservedBeds()) { |
186 |
assert bed.isFree(reservation.getBeginDate(), reservation.getEndDate()) : "One or more of the Beds are still reserved."; |
187 |
} |
188 |
} |
189 |
} |
190 |