1.1 --- a/imiptools/content.py Tue Mar 03 00:03:45 2015 +0100
1.2 +++ b/imiptools/content.py Tue Mar 03 00:05:22 2015 +0100
1.3 @@ -25,7 +25,7 @@
1.4 from imiptools.config import MANAGER_PATH, MANAGER_URL
1.5 from imiptools.data import Object, parse_object, \
1.6 get_address, get_uri, get_value, get_window_end, \
1.7 - is_new_object, uri_dict, uri_item
1.8 + is_new_object, uri_dict, uri_item, uri_values
1.9 from imiptools.dates import format_datetime, get_default_timezone, to_timezone
1.10 from imiptools.period import can_schedule, insert_period, remove_period, \
1.11 remove_affected_period, update_freebusy
1.12 @@ -172,7 +172,17 @@
1.13
1.14 remove_period(freebusy, self.uid, self.recurrenceid)
1.15
1.16 - def _update_freebusy(self, freebusy, periods, recurrenceid):
1.17 + def remove_freebusy_for_original_recurrence(self, freebusy):
1.18 +
1.19 + """
1.20 + Remove from 'freebusy' any specific recurrence from parent free/busy
1.21 + details for the current object.
1.22 + """
1.23 +
1.24 + if self.recurrenceid:
1.25 + remove_affected_period(freebusy, self.uid, self.recurrenceid)
1.26 +
1.27 + def _update_freebusy(self, freebusy, periods, recurrenceid, transp=None):
1.28
1.29 """
1.30 Update the 'freebusy' collection with the given 'periods', indicating an
1.31 @@ -180,25 +190,41 @@
1.32 event.
1.33 """
1.34
1.35 - update_freebusy(freebusy, periods, self.obj.get_value("TRANSP"),
1.36 + update_freebusy(freebusy, periods, transp or self.obj.get_value("TRANSP"),
1.37 self.uid, recurrenceid)
1.38
1.39 - def update_freebusy(self, freebusy, periods):
1.40 + def update_freebusy(self, freebusy, periods, transp=None):
1.41
1.42 """
1.43 Update the 'freebusy' collection for this event with the given
1.44 'periods'.
1.45 """
1.46
1.47 - self._update_freebusy(freebusy, periods, self.recurrenceid)
1.48 + self._update_freebusy(freebusy, periods, self.recurrenceid, transp)
1.49 +
1.50 + def update_freebusy_for_participant(self, freebusy, periods, attr, for_organiser=False):
1.51 +
1.52 + """
1.53 + Update the 'freebusy' collection using the given 'periods', subject to
1.54 + the 'attr' provided for the participant, indicating whether this is
1.55 + being generated 'for_organiser' or not.
1.56 + """
1.57 +
1.58 + # Organisers employ a special transparency.
1.59 +
1.60 + if for_organiser or attr.get("PARTSTAT") != "DECLINED":
1.61 + self.update_freebusy(freebusy, periods, transp=(for_organiser and "ORG" or None))
1.62 + else:
1.63 + self.remove_from_freebusy(freebusy)
1.64
1.65 # Convenience methods for updating stored free/busy information.
1.66
1.67 - def update_freebusy_from_participant(self, user, participant_item):
1.68 + def update_freebusy_from_participant(self, user, participant_item, for_organiser):
1.69
1.70 """
1.71 For the given 'user', record the free/busy information for the
1.72 - 'participant_item' (a value plus attributes).
1.73 + 'participant_item' (a value plus attributes) representing a different
1.74 + identity, thus maintaining a separate record of their free/busy details.
1.75 """
1.76
1.77 participant, participant_attr = participant_item
1.78 @@ -209,19 +235,14 @@
1.79 freebusy = self.store.get_freebusy_for_other(user, participant)
1.80 tzid = self.get_tzid(user)
1.81 window_end = get_window_end(tzid)
1.82 + periods = self.obj.get_periods_for_freebusy(tzid, window_end)
1.83
1.84 - if participant_attr.get("PARTSTAT") != "DECLINED":
1.85 - self.update_freebusy(freebusy,
1.86 - self.obj.get_periods_for_freebusy(tzid, window_end)
1.87 - )
1.88 - else:
1.89 - self.remove_from_freebusy(freebusy)
1.90 + # Record in the free/busy details unless a non-participating attendee.
1.91
1.92 - # Remove any specific recurrence from parent free/busy details.
1.93 + self.update_freebusy_for_participant(freebusy, periods, participant_attr,
1.94 + for_organiser and self.is_not_attendee(participant, self.obj))
1.95
1.96 - if self.recurrenceid:
1.97 - remove_affected_period(freebusy, self.uid, self.recurrenceid)
1.98 -
1.99 + self.remove_freebusy_for_original_recurrence(freebusy)
1.100 self.store.set_freebusy_for_other(user, freebusy, participant)
1.101
1.102 def update_freebusy_from_organiser(self, attendee, organiser_item):
1.103 @@ -231,17 +252,23 @@
1.104 'organiser_item' (a value plus attributes).
1.105 """
1.106
1.107 - self.update_freebusy_from_participant(attendee, organiser_item)
1.108 + self.update_freebusy_from_participant(attendee, organiser_item, True)
1.109
1.110 def update_freebusy_from_attendees(self, organiser, attendees):
1.111
1.112 "For the 'organiser', record free/busy information from 'attendees'."
1.113
1.114 for attendee_item in attendees.items():
1.115 - self.update_freebusy_from_participant(organiser, attendee_item)
1.116 + self.update_freebusy_from_participant(organiser, attendee_item, False)
1.117
1.118 # Logic, filtering and access to calendar structures and other data.
1.119
1.120 + def is_not_attendee(self, identity, obj):
1.121 +
1.122 + "Return whether 'identity' is not an attendee in 'obj'."
1.123 +
1.124 + return identity not in uri_values(obj.get_values("ATTENDEE"))
1.125 +
1.126 def can_schedule(self, freebusy, periods):
1.127 return can_schedule(freebusy, periods, self.uid, self.recurrenceid)
1.128