/*
* Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de)
*
* Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.knurt.fam.template.controller.image.availability;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import de.knurt.fam.core.config.FamCalendarConfiguration;
import de.knurt.fam.core.model.persist.FacilityAvailability;
import de.knurt.fam.core.model.persist.booking.Booking;
import de.knurt.fam.core.persistence.dao.FamDaoProxy;
import de.knurt.fam.core.util.booking.TimeBookingRequest;
import de.knurt.heinzelmann.util.time.SimpleTimeFrame;
import de.knurt.heinzelmann.util.time.TimeFrame;
/**
* factory to produce the availabilities of facilities for images. calendar views
* contains images using facilityavailabilities produced here.
*
* @see FacilityAvailability
* @author Daniel Oltmanns
* @since 0.20090702 (07/02/2009)
*/
public class FacilityAvailability4ImagesGetter {
private TimeFrame day2show;
private TimeBookingRequest br;
private Integer requestedCapacityUnits;
/**
* construct a image getter.
*
* @param br
* a booking request for a facility that must be booked with a time
* rule.
* @param requestedCapacityUnits
*/
public FacilityAvailability4ImagesGetter(TimeBookingRequest br, Integer requestedCapacityUnits) {
this.day2show = SimpleTimeFrame.getDay(br.getRequestedTimeFrame().getCalendarStart());
this.br = br;
this.requestedCapacityUnits = requestedCapacityUnits;
}
private List<FacilityAvailability> getAvailabilitiesWithoutBookingSituation() {
return FamDaoProxy.facilityDao().getFacilityAvailabilitiesMergedByFacilities(this.day2show, this.br.getFacility().getKey());
}
/**
* return a list of {@link FacilityAvailability}s and add dynamicly the
* booking situtation. the list contains all not availabilities (not
* available in general, sudden failures and maintenances) and creates and
* adds new facility availabilities, if there are bookings or applications
* already. all completely availables are not shown here.
*
* if requestedCapacityUnits is <code>null</code>, show orange on partly
* availables. if a positive Integer, assume user wants this capacity units.
* decide between red and green then (on 5 availables, requested 4, 2 are
* booked = red etc.).
*
* @return a list of {@link FacilityAvailability}s and add dynamicly the
* booking situtation.
*/
public List<FacilityAvailability> getAvailabilitiesWithBookingSituation() {
List<FacilityAvailability> result = new ArrayList<FacilityAvailability>();
if (this.br.getFacility().isUnknown()) {
result.addAll(this.getAvailabilitiesWithoutBookingSituation());
} else {
int minuteSteps = FamCalendarConfiguration.smallestMinuteStep();
Calendar start = this.day2show.getCalendarStart();
Calendar end = this.day2show.getCalendarStart();
end.add(Calendar.MINUTE, minuteSteps);
TimeFrame pointer = new SimpleTimeFrame(start, end);
// watch booking situation
List<Booking> bookingsOfEntireDay = FamDaoProxy.bookingDao().getUncanceledBookingsAndApplicationsIn(this.br.getFacility(), this.day2show);
int counterMaybeAvailable = 0;
int counterNotAvailable = 0;
String facilityKey = this.br.getFacility().getKey();
int capacityUnitsOfFacility = this.br.getFacility().getCapacityUnits();
List<FacilityAvailability> availabilitiesWithoutBookingSituation = this.getAvailabilitiesWithoutBookingSituation();
while (this.isRelevant(pointer)) {
boolean generalRulePresent = false;
for (FacilityAvailability da : availabilitiesWithoutBookingSituation) {
if (!da.isCompletelyAvailable() && da.overlaps(pointer)) {
generalRulePresent = true;
}
}
if (!generalRulePresent) {
FacilityAvailability step = new FacilityAvailability(facilityKey, pointer);
// count statuses
counterMaybeAvailable = 0;
counterNotAvailable = 0;
for (Booking b : bookingsOfEntireDay) {
if (b.overlaps(pointer)) {
if (b.isApplication()) {
counterMaybeAvailable += b.getCapacityUnits();
} else if (b.isBooked()) {
counterNotAvailable += b.getCapacityUnits();
}
}
}
if (this.requestedCapacityUnits == null || this.requestedCapacityUnits.intValue() <= 0) {
if (counterNotAvailable >= capacityUnitsOfFacility) {
// ↖ there is a not available and it shall be
// ↖ colored with one time or it is booked up
step.setNotAvailableBecauseOfBooking();
} else if (counterMaybeAvailable > 0 || counterNotAvailable > 0) {
// ↖ there is an application or it is not booked up
// ↖ completely
step.setMaybeAvailable();
}
} else {
if (capacityUnitsOfFacility - counterNotAvailable < this.requestedCapacityUnits.intValue()) {
step.setNotAvailableBecauseOfBooking();
}
}
if (step.isUnset() == false) {
result.add(step);
}
}
pointer.add(Calendar.MINUTE, minuteSteps);
}
result.addAll(availabilitiesWithoutBookingSituation);
}
return result;
}
private boolean isRelevant(TimeFrame pointer) {
return this.isRelevant(pointer.getCalendarStart());
}
private boolean isRelevant(Calendar pointer) {
return pointer.before(this.day2show.getCalendarEnd());
}
}