OOP2

ReservationController.java

1
import java.util.Set;
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