1.1 --- a/docs/preferences.txt Mon Oct 26 17:19:39 2015 +0100
1.2 +++ b/docs/preferences.txt Mon Oct 26 19:07:51 2015 +0100
1.3 @@ -195,3 +195,27 @@
1.4 represented in UTC may have apparently inappropriate hour (and for some zones)
1.5 minute values that correspond to permitted values in this participant's own
1.6 time zone.
1.7 +
1.8 +scheduling_function
1.9 +-------------------
1.10 +
1.11 +Default: schedule_in_freebusy
1.12 +Alternatives: (see below)
1.13 +
1.14 +Indicates the scheduling function used by resources to find an appropriate
1.15 +period for an event. The imiptools.handlers.scheduling module contains the
1.16 +built-in scheduling functions which include the following:
1.17 +
1.18 + schedule_in_freebusy accept an invitation if the event periods
1.19 + are free according to the free/busy
1.20 + records for the resource; decline
1.21 + otherwise
1.22 +
1.23 + schedule_corrected_in_freebusy correct periods in an event according to
1.24 + the permitted_times setting (see above),
1.25 + then attempt to schedule the event
1.26 + according to the free/busy records for the
1.27 + resource
1.28 +
1.29 +The scheduling mechanism can be extended by implementing additional scheduling
1.30 +functions or by extending the handler framework directly.
2.1 --- a/imiptools/handlers/resource.py Mon Oct 26 17:19:39 2015 +0100
2.2 +++ b/imiptools/handlers/resource.py Mon Oct 26 19:07:51 2015 +0100
2.3 @@ -20,9 +20,9 @@
2.4 """
2.5
2.6 from imiptools.data import get_address, to_part, uri_dict
2.7 -from imiptools.dates import ValidityError
2.8 from imiptools.handlers import Handler
2.9 from imiptools.handlers.common import CommonFreebusy, CommonEvent
2.10 +from imiptools.handlers.scheduling import scheduling_functions
2.11
2.12 class ResourceHandler(CommonEvent, Handler):
2.13
2.14 @@ -162,36 +162,15 @@
2.15 invalid requests.
2.16 """
2.17
2.18 - # Check any constraints on the request.
2.19 -
2.20 - try:
2.21 - corrected = self.correct_object()
2.22 -
2.23 - # Refuse to schedule obviously invalid requests.
2.24 + scheduling_function = self.get_preferences().get("scheduling_function", "schedule_in_freebusy")
2.25 + fn = scheduling_functions.get(scheduling_function)
2.26
2.27 - except ValidityError:
2.28 - return None
2.29 -
2.30 - # With a valid request, determine whether the event can be scheduled.
2.31 -
2.32 - # If newer than any old version, discard old details from the
2.33 - # free/busy record and check for suitability.
2.34 + # NOTE: Should signal an error for incorrectly configured resources.
2.35
2.36 - periods = self.get_periods(self.obj)
2.37 -
2.38 - freebusy = self.store.get_freebusy(self.user)
2.39 - offers = self.store.get_freebusy_offers(self.user)
2.40 -
2.41 - # Check the periods against any scheduled events and against
2.42 - # any outstanding offers.
2.43 -
2.44 - scheduled = self.can_schedule(freebusy, periods)
2.45 - scheduled = scheduled and self.can_schedule(offers, periods)
2.46 -
2.47 - # Where the corrected object can be scheduled, issue a counter
2.48 - # request.
2.49 -
2.50 - return scheduled and (corrected and "COUNTER" or "ACCEPTED") or "DECLINED"
2.51 + if not fn:
2.52 + return "DECLINED"
2.53 + else:
2.54 + return fn(self)
2.55
2.56 class Event(ResourceHandler):
2.57
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/imiptools/handlers/scheduling.py Mon Oct 26 19:07:51 2015 +0100
3.3 @@ -0,0 +1,82 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +"""
3.7 +Common scheduling functionality.
3.8 +
3.9 +Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
3.10 +
3.11 +This program is free software; you can redistribute it and/or modify it under
3.12 +the terms of the GNU General Public License as published by the Free Software
3.13 +Foundation; either version 3 of the License, or (at your option) any later
3.14 +version.
3.15 +
3.16 +This program is distributed in the hope that it will be useful, but WITHOUT
3.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.19 +details.
3.20 +
3.21 +You should have received a copy of the GNU General Public License along with
3.22 +this program. If not, see <http://www.gnu.org/licenses/>.
3.23 +"""
3.24 +
3.25 +from imiptools.dates import ValidityError
3.26 +
3.27 +def schedule_in_freebusy(handler):
3.28 +
3.29 + """
3.30 + Attempt to schedule the current object of the given 'handler' in the
3.31 + free/busy schedule of a resource, returning an indication of the kind of
3.32 + response to be returned.
3.33 + """
3.34 +
3.35 + # If newer than any old version, discard old details from the
3.36 + # free/busy record and check for suitability.
3.37 +
3.38 + periods = handler.get_periods(handler.obj)
3.39 +
3.40 + freebusy = handler.store.get_freebusy(handler.user)
3.41 + offers = handler.store.get_freebusy_offers(handler.user)
3.42 +
3.43 + # Check the periods against any scheduled events and against
3.44 + # any outstanding offers.
3.45 +
3.46 + scheduled = handler.can_schedule(freebusy, periods)
3.47 + scheduled = scheduled and handler.can_schedule(offers, periods)
3.48 +
3.49 + return scheduled and "ACCEPTED" or "DECLINED"
3.50 +
3.51 +def schedule_corrected_in_freebusy(handler):
3.52 +
3.53 + """
3.54 + Attempt to schedule the current object of the given 'handler', correcting
3.55 + specified datetimes according to the configuration of a resource,
3.56 + returning an indication of the kind of response to be returned.
3.57 + """
3.58 +
3.59 + # Check any constraints on the request.
3.60 +
3.61 + try:
3.62 + corrected = handler.correct_object()
3.63 +
3.64 + # Refuse to schedule obviously invalid requests.
3.65 +
3.66 + except ValidityError:
3.67 + return None
3.68 +
3.69 + # With a valid request, determine whether the event can be scheduled.
3.70 +
3.71 + scheduled = schedule_in_freebusy(handler)
3.72 +
3.73 + # Where the corrected object can be scheduled, issue a counter
3.74 + # request.
3.75 +
3.76 + return scheduled == "ACCEPTED" and (corrected and "COUNTER" or "ACCEPTED") or "DECLINED"
3.77 +
3.78 +# Registry of scheduling functions.
3.79 +
3.80 +scheduling_functions = {
3.81 + "schedule_in_freebusy" : schedule_in_freebusy,
3.82 + "schedule_corrected_in_freebusy" : schedule_corrected_in_freebusy,
3.83 + }
3.84 +
3.85 +# vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/tests/test_resource_invitation_constraints.sh Mon Oct 26 17:19:39 2015 +0100
4.2 +++ b/tests/test_resource_invitation_constraints.sh Mon Oct 26 19:07:51 2015 +0100
4.3 @@ -34,6 +34,7 @@
4.4 mkdir -p "$PREFS/$USER"
4.5 echo 'Europe/Oslo' > "$PREFS/$USER/TZID"
4.6 echo 'share' > "$PREFS/$USER/freebusy_sharing"
4.7 +echo 'schedule_corrected_in_freebusy' > "$PREFS/$USER/scheduling_function"
4.8 echo '10,12,14,16,18:0,15,30,45' > "$PREFS/$USER/permitted_times"
4.9 echo 'PT60S' > "$PREFS/$USER/freebusy_offers"
4.10
5.1 --- a/tests/test_resource_invitation_constraints_alternative.sh Mon Oct 26 17:19:39 2015 +0100
5.2 +++ b/tests/test_resource_invitation_constraints_alternative.sh Mon Oct 26 19:07:51 2015 +0100
5.3 @@ -34,6 +34,7 @@
5.4 mkdir -p "$PREFS/$USER"
5.5 echo 'Europe/Oslo' > "$PREFS/$USER/TZID"
5.6 echo 'share' > "$PREFS/$USER/freebusy_sharing"
5.7 +echo 'schedule_corrected_in_freebusy' > "$PREFS/$USER/scheduling_function"
5.8 echo '10,12,14,16,18:0,15,30,45' > "$PREFS/$USER/permitted_times"
5.9 echo 'PT60S' > "$PREFS/$USER/freebusy_offers"
5.10