/* * 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.model; import static de.knurt.fam.core.model.persist.FacilityAvailability.BOOKED_NOT_AVAILABLE; import static de.knurt.fam.core.model.persist.FacilityAvailability.BOOKING_MUST_NOT_START_HERE; import static de.knurt.fam.core.model.persist.FacilityAvailability.COMPLETE_AVAILABLE; import static de.knurt.fam.core.model.persist.FacilityAvailability.GENERAL_NOT_AVAILABLE; import static de.knurt.fam.core.model.persist.FacilityAvailability.MAINTENANCE_NOT_AVAILABLE; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import de.knurt.fam.connector.RedirectTarget; import de.knurt.fam.core.aspects.security.auth.SessionAuth; import de.knurt.fam.core.config.FamRequestContainer; import de.knurt.fam.core.model.config.BookingStrategy; import de.knurt.fam.core.model.config.Facility; import de.knurt.fam.core.model.config.FacilityBookable; 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.persistence.dao.config.FacilityConfigDao; import de.knurt.fam.core.util.mvc.QueryKeys; import de.knurt.fam.core.util.mvc.QueryStringBuilder; import de.knurt.fam.core.util.mvc.RedirectResolver; import de.knurt.fam.core.util.mvc.RequestInterpreter; import de.knurt.fam.core.util.time.CalendarViewResolver; import de.knurt.fam.core.util.time.FamCalendar; import de.knurt.fam.core.view.html.calendar.AvailabilityOverviewHtml; import de.knurt.fam.core.view.html.calendar.FamMonthAvailabilityHtml; import de.knurt.fam.core.view.html.calendar.FamMonthHtml; import de.knurt.fam.core.view.html.calendar.FamWeekAvailabilityHtml; import de.knurt.fam.core.view.html.calendar.FamWeekHtml; import de.knurt.fam.core.view.html.calendar.factory.AvailabilityInputHtmlFactory; import de.knurt.fam.core.view.html.calendar.factory.FamCalendarHtmlFactory; import de.knurt.fam.core.view.text.FamDateFormat; import de.knurt.fam.core.view.text.FamText; import de.knurt.heinzelmann.ui.html.HtmlElement; import de.knurt.heinzelmann.ui.html.HtmlFactory; import de.knurt.heinzelmann.util.adapter.ComparableCollectionsAdapter; import de.knurt.heinzelmann.util.query.QueryString; import de.knurt.heinzelmann.util.query.QueryStringFactory; import de.knurt.heinzelmann.util.time.TimeFrame; /** * control the pages, where you can set the general availability in a calendar. * delegate between calendar views and overviews and handle the request and its * containing date in the right context. * * model factory for resource named <code>systemfacilityavailability</code> * * @author Daniel Oltmanns * @since 0.20090421 (04/21/2009) */ @SuppressWarnings("deprecation") // TODO #11 kill uses of deprecations public class FacilityAvailabilityModelFactory { private HtmlElement getTimeInput(HttpServletRequest request) { HtmlElement result = HtmlFactory.get("div"); Integer interval = RequestInterpreter.getInterval(request); if (interval != null) { HtmlElement pStart = HtmlFactory.get("p"); HtmlElement labeldiv = HtmlFactory.get("span", "Start time:"); // INTLANG pStart.add(labeldiv + HtmlFactory.get("br").toString()); HtmlElement pEnd = HtmlFactory.get("p"); labeldiv = HtmlFactory.get("span", "End time:"); // INTLANG pEnd.add(labeldiv + HtmlFactory.get("br").toString()); Calendar today = Calendar.getInstance(); if (interval.intValue() == FacilityAvailability.ONE_TIME) { pStart.add(FamCalendarHtmlFactory.getDateSelect(today, 365, QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_DAY, 0, true)); pEnd.add(FamCalendarHtmlFactory.getDateSelect(today, 365, QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_DAY, 1, true)); } else if (interval.intValue() == FacilityAvailability.EACH_YEAR) { Calendar firstDayOfYear = Calendar.getInstance(); firstDayOfYear.set(Calendar.DAY_OF_YEAR, 1); pStart.add(FamCalendarHtmlFactory.getDateSelect(firstDayOfYear, 365, QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_YEAR), false)); pEnd.add(FamCalendarHtmlFactory.getDateSelect(firstDayOfYear, 365, QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_YEAR) + 1, false)); } else if (interval.intValue() == FacilityAvailability.EACH_MONTH) { int i = 1; Calendar firstDayOfMonth = Calendar.getInstance(); firstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1); List<String> optiontexts = new ArrayList<String>(); while (i <= 28) { optiontexts.add(FamDateFormat.getNumeralFormat(i)); i++; } pStart.add(FamCalendarHtmlFactory.getDateSelect(firstDayOfMonth, QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_MONTH) - 1, optiontexts)); pEnd.add(FamCalendarHtmlFactory.getDateSelect(firstDayOfMonth, QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_MONTH), optiontexts)); } else if (interval.intValue() == FacilityAvailability.EACH_WEEK) { Calendar weekday = FamCalendar.getInstance(); weekday.set(Calendar.DAY_OF_WEEK, weekday.getFirstDayOfWeek()); int pointer = 0; List<String> optiontexts = new ArrayList<String>(); while (pointer < 7) { optiontexts.add(weekday.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, FamRequestContainer.locale())); weekday.add(Calendar.DAY_OF_YEAR, 1); pointer++; } weekday.add(Calendar.DAY_OF_YEAR, -7); pStart.add(FamCalendarHtmlFactory.getDateSelect(weekday, QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_WEEK) - 1, optiontexts)); pEnd.add(FamCalendarHtmlFactory.getDateSelect(weekday, QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_DAY, today.get(Calendar.DAY_OF_WEEK), optiontexts)); } else { // each day or each hour QueryString qs = QueryStringFactory.get(QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_DAY, QueryKeys.getEncodeStringOfDate(today)); pStart.add(qs.getAsHtmlInputsTypeHidden()); List<String> optiontexts = new ArrayList<String>(2); optiontexts.add("same day"); // INTLANG optiontexts.add("next day"); // INTLANG pEnd.add(FamCalendarHtmlFactory.getDateSelect(today, QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_DAY, 0, optiontexts)); } pStart.add(FamCalendarHtmlFactory.getTimeSelectCompact(QueryKeys.QUERY_KEY_FROM + QueryKeys.QUERY_KEY_HOUR_OF_DAY, 0)); pEnd.add(FamCalendarHtmlFactory.getTimeSelectCompact(QueryKeys.QUERY_KEY_TO + QueryKeys.QUERY_KEY_HOUR_OF_DAY, 0)); result.add(pStart); result.add(pEnd); } return result; } private HtmlElement getSummary(HttpServletRequest request) { HtmlElement result = HtmlFactory.get("ul").addClassName("asList"); HtmlElement warningSpan = HtmlFactory.get("span").addClassName("warning"); // summary availability Integer availability = RequestInterpreter.getAvailability(request); // is valid availability if (availability != null && (availability == COMPLETE_AVAILABLE || availability == GENERAL_NOT_AVAILABLE || availability == BOOKED_NOT_AVAILABLE || availability == MAINTENANCE_NOT_AVAILABLE || availability == BOOKING_MUST_NOT_START_HERE)) { result.add(HtmlFactory.get("li").add(HtmlFactory.get("strong").add("Availability")).add(": ").add(FamText.facilityAvailability(availability))); // INTLANG; } // summary interval Integer interval = RequestInterpreter.getInterval(request); if (interval != null) { result.add(HtmlFactory.get("li").add(HtmlFactory.get("strong").add("Interval")).add(": ").add(FamText.message("calendar.iteration." + interval))); // INTLANG; } // summary notice String notice = RequestInterpreter.getNotice(request); if (notice != null) { result.add(HtmlFactory.get("li").add(HtmlFactory.get("strong").add("Notice")).add(": ").add(notice)); // INTLANG; } if (availability != null && availability.intValue() != FacilityAvailability.COMPLETE_AVAILABLE) { FacilityAvailability da = RequestInterpreter.getCompleteFacilityAvailabilityForInsertion(request, SessionAuth.user(request)); if (da != null) { TimeFrame baseTimeFrame = da.getBasePeriodOfTime(); if (baseTimeFrame != null) { String timeText = interval == FacilityAvailability.ONE_TIME ? "Coming into effect" : "First time coming into effect"; // INTLANG result.add(HtmlFactory.get("li").add(HtmlFactory.get("strong").add(timeText)).add(": ").add(baseTimeFrame)); // summarize bookings being canceled List<Facility> facilities = new ArrayList<Facility>(); facilities.add(da.getFacility()); List<Booking> bookings = FamDaoProxy.bookingDao().getAll(facilities); int negativeAnswers = 0; for (Booking booking : bookings) { if (!booking.isCanceled() && !booking.sessionAlreadyBegun() && booking.getIdBookedInBookingStrategy() != BookingStrategy.QUEUE_BASED && da.applicableTo(booking.getSessionTimeFrame())) { negativeAnswers++; } } result.add(HtmlFactory.get("li").add(HtmlFactory.get("strong").add("Number of letters of refusal sent with this input")).add(": ").add(negativeAnswers == 0 ? "no letter" : warningSpan.setContent(negativeAnswers + " letter(s)").toString())); // INTLANG; // warning on nothing set or left long durationOfBaseTime = baseTimeFrame.getDuration(); long durationOfAnHour = 1000l * 60 * 60; boolean willBlockResource = false; boolean nothingSet = durationOfBaseTime <= 0; if (!nothingSet && interval != FacilityAvailability.ONE_TIME && availability != FacilityAvailability.COMPLETE_AVAILABLE) { if ((interval == FacilityAvailability.EACH_YEAR && durationOfBaseTime >= durationOfAnHour * 24 * 365) || (interval == FacilityAvailability.EACH_MONTH && durationOfBaseTime >= durationOfAnHour * 24 * 365 / 12) || (interval == FacilityAvailability.EACH_WEEK && durationOfBaseTime >= durationOfAnHour * 24 * 7) || (interval == FacilityAvailability.EACH_DAY && durationOfBaseTime >= durationOfAnHour * 24) || (interval == FacilityAvailability.EACH_HOUR && durationOfBaseTime >= durationOfAnHour)) { willBlockResource = true; } } if (willBlockResource) { result.add(HtmlFactory.get("li").add(warningSpan.setContent("If setting this, the facility will never ever be available!"))); // INTLANG; } if (nothingSet) { result.add(HtmlFactory.get("li").add(warningSpan.setContent("The duration of your setting is 0!"))); // INTLANG; } } } } return result; } private FamWeekHtml getDasWeekHtml(Calendar cal, String facilityKey, HttpServletRequest request) { boolean showRedGreenOnly = RequestInterpreter.hasAjaxFlag(request); return new FamWeekAvailabilityHtml(cal, facilityKey, new AvailabilityInputHtmlFactory(facilityKey, cal), showRedGreenOnly, true); } private FamMonthHtml getDasMonthHtml(Calendar cal, String facilityKey, HttpServletRequest request) { boolean showRedGreenOnly = RequestInterpreter.hasAjaxFlag(request); return new FamMonthAvailabilityHtml(cal, new AvailabilityInputHtmlFactory(facilityKey, cal), "onemonthday", facilityKey, showRedGreenOnly, true); } private String getOverviewHtml(TemplateResource templateResource, Calendar cal, String facilityKey) { List<FacilityAvailability> das = FamDaoProxy.facilityDao().getFacilityAvailabilitiesFollowingParents(facilityKey); if (this.suddenFailureIsActive(das)) { return ""; } else { ComparableCollectionsAdapter.getInstance().setModusToAll(das, FacilityAvailability.COMPARE_BY_DATE_SET); Collections.sort(das); return new AvailabilityOverviewHtml(cal, facilityKey, das, templateResource.getAuthUser()).toString(); } } private boolean suddenFailureIsActive(String facilityKey) { List<FacilityAvailability> das = FamDaoProxy.facilityDao().getFacilityAvailabilitiesFollowingParents(facilityKey); return this.suddenFailureIsActive(das); } private boolean suddenFailureIsActive(List<FacilityAvailability> das) { boolean result = false; for (FacilityAvailability da : das) { if (da.isNotAvailableBecauseOfSuddenFailure() && !da.getBasePeriodOfTime().endsInPast()) { result = true; break; } } return result; } /** * return the calendar view requested. * * @param rq * request got * @return the calendar view requested */ private String getCalendarView(HttpServletRequest rq) { String calView = rq.getParameter(QueryKeys.QUERY_KEY_CALENDAR_VIEW); if (calView == null || QueryStringBuilder.isValidCalendarView(calView) == false) { Facility d = RequestInterpreter.getFacility(rq); if (d == null) { calView = CalendarViewResolver.getInstance().getDefaultCalendarView(FacilityConfigDao.getUnknownBookableFacility()); } else { calView = CalendarViewResolver.getInstance().getDefaultCalendarView(d); } } return calView; } private Calendar getCalendar(HttpServletRequest rq) { if (rq.getParameter(QueryKeys.QUERY_KEY_SHOW_DETAILS) != null) { return RequestInterpreter.getCalendarStart(rq.getParameter(QueryKeys.QUERY_KEY_SHOW_DETAILS)); } else { return RequestInterpreter.getCalendar(rq); } } /** * return the calendar matching the given request and facility. * * @param rq * request got * @param facilityKey * representing a facility * @return the calendar matching the given request and facility. */ private String getCalendarHtml(TemplateResource templateResource, String facilityKey) { Calendar cal = this.getCalendar(templateResource.getRequest()); String result = ""; String calView = this.getCalendarView(templateResource.getRequest()); if (calView.equals(QueryKeys.WEEK)) { FamWeekHtml calhtml = this.getDasWeekHtml(cal, facilityKey, templateResource.getRequest()); result = calhtml.toString(); } else if (calView.equals(QueryKeys.MONTH)) { // month view FamMonthHtml calhtml = this.getDasMonthHtml(cal, facilityKey, templateResource.getRequest()); result = calhtml.toString(); } else { // over view result = this.getOverviewHtml(templateResource, cal, facilityKey); } return result; } public Properties getProperties(TemplateResource templateResource) { Properties result = new Properties(); String facilityKey = templateResource.getRequest().getParameter(QueryKeys.QUERY_KEY_FACILITY); boolean is_overview = this.getCalendarView(templateResource.getRequest()).equals(QueryKeys.OVERVIEW); Facility facility = RequestInterpreter.getFacility(templateResource.getRequest()); if (facility == null) { // ↖ wrong url! RedirectResolver.redirectClient(RedirectTarget.SYSTEM_FACILITY_AVAILABILITY_OVERVIEW, templateResource); } else { result.put("queue_based", facility.isBookable() && FacilityConfigDao.bookingRule(facilityKey).getBookingStrategy() == BookingStrategy.QUEUE_BASED); result.put("facility_name", FacilityConfigDao.getInstance().getLabel(facilityKey)); result.put("content", this.getCalendarHtml(templateResource, facilityKey)); QueryString link_overview = QueryStringFactory.get(QueryKeys.QUERY_KEY_CALENDAR_VIEW, QueryKeys.OVERVIEW); link_overview.put(QueryKeys.QUERY_KEY_FACILITY, facilityKey); result.put("link_hidden_inputs", link_overview.getAsHtmlInputsTypeHidden()); result.put("text_facilitykey", facilityKey); result.put("name_facilitykey", QueryKeys.QUERY_KEY_FACILITY); if (is_overview) { result.put("link_overview", link_overview.getAsHtmlLinkHref() + "#newrule"); result.put("link_overview_text", "Add a new rule"); // INTLANG result.put("add_or_edit", "add"); } else { result.put("link_overview", link_overview.getAsHtmlLinkHref()); result.put("link_overview_text", "Edit availability rules"); // INTLANG result.put("add_or_edit", "edit"); } link_overview.put(QueryKeys.QUERY_KEY_CALENDAR_VIEW, QueryKeys.WEEK); result.put("link_weekview", link_overview.getAsHtmlLinkHref()); link_overview.put(QueryKeys.QUERY_KEY_CALENDAR_VIEW, QueryKeys.MONTH); result.put("link_monthview", link_overview.getAsHtmlLinkHref()); // has many units boolean hasChildren = facility.hasChildren(); int units = facility.isBookable() ? ((FacilityBookable) facility).getCapacityUnits() : 1; result.put("flag_hasmanyunits", units > 1); result.put("flag_haschildren", hasChildren); if (hasChildren) { result.put("number_children", facility.getChildren().size()); } else { result.put("number_children", ""); } if (units > 1) { result.put("string_nameofunits", FamText.capacityUnits((FacilityBookable) facility)); } else { result.put("string_nameofunits", ""); } // set edit form boolean suddenFailureIsActive = this.suddenFailureIsActive(facilityKey); if (is_overview && !suddenFailureIsActive) { // show "add a rule" result.put("show_edit", true); result.put("show_suddenFailureIsActive", false); result.put("querystring", QueryStringBuilder.getBigCalendarQueryString(facilityKey, RequestInterpreter.getCalendar(templateResource.getRequest()), QueryKeys.OVERVIEW)); // get current step int currentStep = 1; try { currentStep = Integer.parseInt(RequestInterpreter.getOf(templateResource.getRequest())); } catch (NumberFormatException e) { } // ← stay step 1 QueryString hiddenInputs = null; // ↘ it is the final sending of add new rule if (currentStep >= 4) { hiddenInputs = new QueryString(); hiddenInputs.put(QueryKeys.QUERY_KEY_FACILITY, facilityKey); hiddenInputs.put(QueryKeys.QUERY_KEY_CALENDAR_VIEW, QueryKeys.OVERVIEW); currentStep = 1; } else { hiddenInputs = QueryStringFactory.getInstance().get(templateResource.getRequest()); } hiddenInputs.put(QueryKeys.QUERY_KEY_OF, currentStep + 1); // ↘ set flag: nothing shall be deleted when submit form hiddenInputs.put(QueryKeys.QUERY_KEY_DELETE, "-1"); switch (currentStep) { case 1: // choose of availability result.put("name_available", QueryKeys.QUERY_KEY_AVAILABLILITY); result.put("value_available_nomaintenance", FacilityAvailability.MAINTENANCE_NOT_AVAILABLE); result.put("text_available_nomaintenance", FamText.facilityAvailability(FacilityAvailability.MAINTENANCE_NOT_AVAILABLE)); result.put("value_available_noingeneral", FacilityAvailability.GENERAL_NOT_AVAILABLE); result.put("text_available_noingeneral", FamText.facilityAvailability(FacilityAvailability.GENERAL_NOT_AVAILABLE)); result.put("value_available_mustnotstarthere", FacilityAvailability.BOOKING_MUST_NOT_START_HERE); result.put("text_available_mustnotstarthere", FamText.facilityAvailability(FacilityAvailability.BOOKING_MUST_NOT_START_HERE)); result.put("value_available_available", FacilityAvailability.COMPLETE_AVAILABLE); result.put("text_available_available", FamText.facilityAvailability(FacilityAvailability.COMPLETE_AVAILABLE)); // choose interval result.put("name_interval", QueryKeys.QUERY_KEY_ITERATION); result.put("value_interval_onetime", FacilityAvailability.ONE_TIME); result.put("value_interval_yearly", FacilityAvailability.EACH_YEAR); result.put("value_interval_monthly", FacilityAvailability.EACH_MONTH); result.put("value_interval_weekly", FacilityAvailability.EACH_WEEK); result.put("value_interval_daily", FacilityAvailability.EACH_DAY); break; case 2: result.put("text_info", this.getSummary(templateResource.getRequest())); result.put("select_time", this.getTimeInput(templateResource.getRequest())); result.put("name_notice", QueryKeys.QUERY_KEY_TEXT_NOTICE); break; case 3: result.put("text_info", this.getSummary(templateResource.getRequest())); break; } // set current step result.put("current_step", currentStep); result.put("hiddenInputs", hiddenInputs.getAsHtmlInputsTypeHidden()); } else if (suddenFailureIsActive) { result.put("show_edit", false); result.put("show_suddenFailureIsActive", true); result.put("text_facilitykey", facilityKey); result.put("name_facilitykey", QueryKeys.QUERY_KEY_FACILITY); result.put("value_yes", QueryKeys.YES); result.put("name_yes", QueryKeys.QUERY_KEY_YES_NO); result.put("querystring", QueryStringBuilder.getBigCalendarQueryString(facilityKey, RequestInterpreter.getCalendar(templateResource.getRequest()), QueryKeys.OVERVIEW)); } else { // it is not the overview / editing view result.put("show_edit", false); result.put("show_suddenFailureIsActive", false); } } return result; } }