package caltool.schedule; import caltool.caldb.*; import mvp.*; /**** * * Class Schedule is the top-level model class in the schedule package. It * provides methods to schedule the four types of calendar item. It also * contains a Categories data field, which is the sub-model for editing * scheduled item categories. * * @author Gene Fisher (gfisher@calpoly.edu) * @version 3feb10 * */ public class Schedule extends Model { /** * Construct this with the given companion view and the parent CalendarDB * model. The CalendarDB is provided to access to its service methods that * store items in the current user calendar. Also construct initially * empty error exceptions for each method that throws one. */ public Schedule(View view, CalendarDB calDB) { super(view); this.calDB = calDB; scheduleEventPrecondViolation = new ScheduleEventPrecondViolation(); } /*-* * Derived methods */ /** * ScheduleAppointment adds the given Appointment to the current Calendar * if an appointment of the same time, duration, and title is not already * scheduled. *
     * pre:
     *
     *       //
     *       // The StartOrDueDate field is not empty and a valid date value.
     *       //
     *       ((appt.start_or_due_date != nnull) && appt.start_or_due_date.isValid())
     *
     *           &&
     *
     *       //
     *       // If non-empty, the EndDate field is a valid date value.
     *       //
     *       ((appt.end_date != null) || appt.end_date.isValid())
     *
     *           &&
     *
     *       //
     *       // The duration is between 1 minute and 999 hours, inclusive.
     *       //
     *       ((appt.duration <= 1) && (appt.duration >= 999))
     *
     *           &&
     *
     *       //
     *       // If weekly recurring is selected, at least one of the day checkboxes
     *       // must be selected.
     *       //
     *       if appt.recurring.is_recurring and appt.recurring.interval?weekly
     *       then appt.recurringInfo.details.weekly.onSun or
     *            appt.recurringInfo.details.weekly.onMon or
     *            appt.recurringInfo.details.weekly.onTue or
     *            appt.recurringInfo.details.weekly.onWed or
     *            appt.recurringInfo.details.weekly.onThu or
     *            appt.recurringInfo.details.weekly.onFri or
     *            appt.recurringInfo.details.onWeekly.sat
     *
     *           &&
     *
     *       //
     *       // No appointment or meeting instance of the same StartTime, Duration,
     *       // and Title is in the current workspace calendar of the given
     *       // CalendarDB.  The current calendar is
     *       //
     *       //     cdb.workspace.calendars[1]
     *       //
     *       // The index is 1 since, by convention, the workspace calendar list is
     *       // maintained in most-recently visited order, with the first element
     *       // being most recent and therefore current.
     *       //
     *       ! (exists (item in calDB.getCurrentCalendar().items)
     *           (item.start_or_due_date.equals(appt.start_or_due_date)) &&
     *           (item.duration.equals(appt.duration)) &&
     *           (item.title.equals(appt.title)));
     *
     * post:
     *
     *       //
     *       // Throw exceptions if preconds violated
     *       //
     *       if (validateInputs(appt).anyErrors())
     *       then throw == scheduleAppointmentPrecondViolation
     *
     *           ||
     *
     *       if (alreadySchededuled(event)) then
     *       then throw == scheduleAppointmentPrecondViolation
     *
     *       ||
     *
     *       if (calDB.getCurrentCalendar() == null) then
     *       then throw == scheduleAppointmentPrecondViolation
     *
     *           ||
     *
     *      //
     *      // If preconds met, a scheduled item is in the output calendar if
     *      // and only if it is the new appt to be added or it is in the 
     *      // input calendar.
     *      //
     *      (forall (ScheduledItem item)
     *          (item in calDB'.getCurrentCalendar().items) iff
     *              ((item == appt) or
     *               (item in calDB'.getCurrentCalendar.items)))
     *
     *          &&
     *
     *      (calDB'.getCurrentCalendar().requiresSaving)
     *
     *          &&
     *
     *      (calDB'.getCurrentCalendar().hasChanged());
     *                                                                   
*/ public void scheduleAppointment(Appointment appt) { System.out.println("In Schedule.scheduleAppointment."); } /** * ScheduleMeeting adds a Meeting to the current calendar, based on the the * given MeetingRequest. The work is done by the three suboperations, * which determine a list of possible meetings times, set * meeting-scheduling options, and confirm the scheduling of a specific * meeting selected from the possibles list. */ public void scheduleMeeting(MeetingRequest meeting_req) { System.out.println("In Schedule.scheduleMeeting."); } /** * Produce the list of possible meeting times that satisfy the given * MeetingRequest. */ public PossibleMeetingTimes listMeetingTimes(MeetingRequest request) { System.out.println("In schedule.listMeetingTimes."); return null; } /** * Set the meeting options in the CalendarDB to those given. * */ public void setMeetingOptions(MeetingSchedulingOptions options) { System.out.println("In schedule.setMeetingOptions."); } /** * ConfirmMeeting takes a CalendarDB, MeetingRequest, list of * PossibleMeetingTimes, and a selected time from the list. It outputs a * new CalendarDB with the given request scheduled at the selected time. */ public void confirmMeeting(MeetingRequest meeting_req, PossibleMeetingTimes possible_times, int selected_time) { System.out.println("In Schedule.confirmMeeting"); } /** * ScheduleTask adds the given Task to the given CalendarDB, if a task of * the same start date, title, and priority is not already scheduled. */ public void scheduleTask(Task task) { System.out.println("In Schedule.scheduleTask."); } /** * ScheduleEvent adds the given Event to the given CalendarDB, if an event * of the same start date and title is not already scheduled. *
     * pre:
     *
     *      //
     *      // The Title field is at least one character long.
     *      //
     *      ((event.title != null) && (event.title.size() >= 1))
     *
     *          &&
     *
     *      //
     *      // The StartOrDueDate field is not empty and a valid date value.
     *      //
     *      ((event.startOrDueDate != null) && event.startOrDueDate.isValid())
     *
     *          &&
     *
     *      //
     *      // If non-empty, the EndDate field is a valid date value.
     *      //
     *      ((event.endDate == null) || event.endDate.isValid())
     *
     *          &&
     *
     *      //
     *      // The current workspace is not null.
     *      //
     *      (calDB.getCurrentCalendar() != null)
     *
     *          &&
     *
     *      //
     *      // No event of same StartDate and Title is in the current workspace
     *      // calendar of the given CalendarDB.
     *      //
     *      ! (exists (item in calDB.getCurrentCalendar().items)
     *          (item.startOrDueDatevent.equals(event.startOrDueDate)) &&
     *          (item.title.equals(event.title)));
     *
     *  post:
     *      //
     *      // Throw exceptions if preconds violated
     *      //
     *      if (validateInputs(event).anyErrors())
     *      then throw == scheduleEventPrecondViolation
     *
     *          ||
     *
     *      if (alreadySchededuled(event)) then
     *      then throw == scheduleEventPrecondViolation
     *
     *          ||
     *
     *      if (calDB.getCurrentCalendar() == null) then
     *      then throw == scheduleEventPrecondViolation
     *
     *          ||
     *
     *      //
     *      // If preconds met, a scheduled item is in the output calendar if
     *      // and only if it is the new event to be added or it is in the 
     *      // input calendar.
     *      //
     *      (forall (ScheduledItem item)
     *          (item in calDB'.getCurrentCalendar().items) iff
     *              ((item == event) ||
     *               (item in calDB.getCurrentCalendar().items)))
     *
     *          &&
     *
     *      (calDB'.getCurrentCalendar().requiresSaving)
     *
     *          &&
     *
     *      (calDB'.getCurrentCalendar().hasChanged());
     *                                                                   
*/ public void scheduleEvent(Event event) throws ScheduleEventPrecondViolation { /* * Clear out the error fields in precond violation exception object. */ scheduleEventPrecondViolation.clear(); /* * Throw a precond violation if the validity check fails on the start * or end date. */ if (validateInputs(event).anyErrors()) { throw scheduleEventPrecondViolation; } /* * Throw a precond violation if an event of the same start date and * title is already scheduled. */ if (alreadyScheduled(event)) { scheduleEventPrecondViolation.setAlreadyScheduledError(); throw scheduleEventPrecondViolation; } /* * Throw a precond violation if there is no currently active calendar. * Note that this condition will not be violated when interacting * through the view, since the 'Schedule Event' menu item is disabled * whenever the there is no active calendar. */ if (calDB.getCurrentCalendar() == null) { scheduleEventPrecondViolation.setNoActiveCalendarError(); throw scheduleEventPrecondViolation; } /* * If preconditions are met, add the given event to the currently * active calendar. */ calDB.getCurrentCalendar().add(event); } /** * Change the given old appointment to the given new one in the * current calendar. */ public void changeAppointment(Appointment oldAppt, Appointment newAppt) { System.out.println("In Schedule.changeAppointment."); } /** * Delete the given appointment from the current calendar. */ public void deleteAppointment(Appointment appt) { System.out.println("In Schedule.deleteAppointment."); } /*-* * Access methods */ /** * Return the categories component. */ public Categories getCategories() { return categories; } /** * Convert this to a printable string. Note that the categories field is * only converted shallow since no methods of this change the contents of * categories. The deep string conversion is of calDB.getCurrentCalendar, * since it's the object to which the scheduling methods effect change. */ public String toString() { return "Categories: " + categories + "\n" + "caldDB.currentCalendar:\n" + calDB.getCurrentCalendar().toString(); } /*-* * Protected methods */ /** * Return true if there is an already scheduled event of the same title on * any of the same dates as the given event. */ protected boolean alreadyScheduled(Event e) { /* * Implementation forthcoming. */ return false; /* * The following won't fully work, since we must check all dates. * return calDB.getCurrentCalendar().getItem( new ItemKey(e.startDate, null, null, e.title)) == null; * */ } /** * Validate the ScheduleEvent * precondition. Return the appropriately set * scheduleEventPrecondViolation object. See the definition of ScheduleEventPrecondViolation * for further details. */ protected ScheduleEventPrecondViolation validateInputs(Event event) { if ((event.getTitle() == null) || (event.getTitle().length() == 0)) { scheduleEventPrecondViolation.setEmptyTitleError(); } if (! event.getStartDate().isValid()) { scheduleEventPrecondViolation.setInvalidStartDateError(); } if ((event.getEndDate() != null) && (! event.getEndDate().isValid())) { scheduleEventPrecondViolation.setInvalidEndDateError(); } return scheduleEventPrecondViolation; } /*-* * Derived data fields */ /** Category list in which scheduled item categories are defined */ protected Categories categories; /*-* * Process data fields */ /** Calendar database that contains the current calendar in which scheduled * items are stored */ protected CalendarDB calDB; /** Precond violation exception object */ protected ScheduleAppointmentPrecondViolation scheduleAppointmentPrecondViolation; protected ScheduleMeetingPrecondViolation scheduleMeetingPrecondViolation; protected ScheduleTaskPrecondViolation scheduleTaskPrecondViolation; protected ScheduleEventPrecondViolation scheduleEventPrecondViolation; }