1.1 --- a/imiptools/handlers/common.py Tue Apr 19 17:57:28 2016 +0200
1.2 +++ b/imiptools/handlers/common.py Tue Apr 19 18:17:06 2016 +0200
1.3 @@ -143,34 +143,49 @@
1.4
1.5 self.add_result("REFRESH", [get_address(organiser)], obj.to_part("REFRESH"))
1.6
1.7 - def ensure_occurrence(self):
1.8 + def is_newly_separated_occurrence(self):
1.9
1.10 - """
1.11 - Ensure that the object originating from an attendee corresponds to an
1.12 - existing occurrence of an event, creating or reviving a specific
1.13 - recurrence if necessary.
1.14 -
1.15 - Return whether a valid occurrence was found.
1.16 - """
1.17 + "Return whether the current object is a newly-separated occurrence."
1.18
1.19 # Obtain any stored object.
1.20
1.21 obj = self.get_stored_object_version()
1.22
1.23 - # Handle any newly-defined occurrence.
1.24 + # Handle any newly-separated, valid occurrence.
1.25 +
1.26 + return not obj and self.is_recurrence()
1.27 +
1.28 + def make_separate_occurrence(self, for_organiser=False):
1.29
1.30 - if not obj:
1.31 + """
1.32 + Set the current object as a separate occurrence and redefine free/busy
1.33 + records in terms of this new occurrence for other participants.
1.34 + """
1.35
1.36 - # Check for a valid occurrence.
1.37 + parent = self.get_parent_object()
1.38 + if not parent:
1.39 + return False
1.40 +
1.41 + # Transfer attendance information from the parent.
1.42
1.43 - if not self.is_recurrence():
1.44 - return False
1.45 + parent_attendees = uri_dict(parent.get_value_map("ATTENDEE"))
1.46 + attendee_map = uri_dict(self.obj.get_value_map("ATTENDEE"))
1.47 +
1.48 + for attendee, attendee_attr in parent_attendees.items():
1.49 + if not attendee_map.has_key(attendee):
1.50 + attendee_map[attendee] = attendee_attr
1.51
1.52 - # Set the complete event if not an additional occurrence. For any newly-
1.53 - # indicated occurrence, use the received event details.
1.54 + self.obj["ATTENDEE"] = attendee_map.items()
1.55 + self.obj.remove_all(["RDATE", "RRULE"])
1.56 +
1.57 + # Create or revive the occurrence.
1.58
1.59 - self.store.remove_cancellation(self.user, self.uid, self.recurrenceid)
1.60 - self.store.set_event(self.user, self.uid, self.recurrenceid, self.obj.to_node())
1.61 + self.store.remove_cancellation(self.user, self.uid, self.recurrenceid)
1.62 + self.store.set_event(self.user, self.uid, self.recurrenceid, self.obj.to_node())
1.63 +
1.64 + # Update free/busy details for the current object for all attendees.
1.65 +
1.66 + self.update_freebusy_from_attendees(attendee_map.keys())
1.67
1.68 return True
1.69
2.1 --- a/imiptools/handlers/person.py Tue Apr 19 17:57:28 2016 +0200
2.2 +++ b/imiptools/handlers/person.py Tue Apr 19 18:17:06 2016 +0200
2.3 @@ -205,15 +205,23 @@
2.4
2.5 "As organiser, update attendance from valid attendees."
2.6
2.7 - if not self.ensure_occurrence():
2.8 - return False
2.9 + # Occurrences that are still part of a parent object are separated,
2.10 + # attendance information transferred, and the free/busy details updated.
2.11 +
2.12 + if self.is_newly_separated_occurrence():
2.13 + if self.make_separate_occurrence(for_organiser=True):
2.14 +
2.15 + # Update free/busy details for the event.
2.16 +
2.17 + self.update_event_in_freebusy(for_organiser=True)
2.18 + return True
2.19
2.20 # Merge the attendance for the received object.
2.21
2.22 - if self.merge_attendance(attendees):
2.23 - self.update_freebusy_from_attendees(attendees)
2.24 + elif self.merge_attendance(attendees):
2.25 + return self.update_freebusy_from_attendees(attendees)
2.26
2.27 - return True
2.28 + return False
2.29
2.30 def _refresh(self, organiser, attendees):
2.31
3.1 --- a/imiptools/handlers/person_outgoing.py Tue Apr 19 17:57:28 2016 +0200
3.2 +++ b/imiptools/handlers/person_outgoing.py Tue Apr 19 18:17:06 2016 +0200
3.3 @@ -120,14 +120,19 @@
3.4 self.store.remove_cancellation(self.user, self.uid, self.recurrenceid)
3.5
3.6 else:
3.7 - if not self.ensure_occurrence():
3.8 - return False
3.9 + # Occurrences that are still part of a parent object are separated,
3.10 + # attendance information transferred, and the free/busy details
3.11 + # updated.
3.12 +
3.13 + if self.is_newly_separated_occurrence():
3.14 + self.make_separate_occurrence(for_organiser=not from_organiser)
3.15
3.16 # Obtain valid attendees, merging their attendance with the stored
3.17 # object.
3.18
3.19 - attendees = self.require_attendees(from_organiser)
3.20 - self.merge_attendance(attendees)
3.21 + else:
3.22 + attendees = self.require_attendees(from_organiser)
3.23 + self.merge_attendance(attendees)
3.24
3.25 # Remove any associated request.
3.26