imip-agent

imiptools/handlers/resource.py

251:f506b093407b
2015-02-03 Paul Boddie The Freebusy handler does not need the ResourceHandler functionality.
     1 #!/usr/bin/env python     2      3 """     4 Handlers for a resource.     5      6 Copyright (C) 2014, 2015 Paul Boddie <paul@boddie.org.uk>     7      8 This program is free software; you can redistribute it and/or modify it under     9 the terms of the GNU General Public License as published by the Free Software    10 Foundation; either version 3 of the License, or (at your option) any later    11 version.    12     13 This program is distributed in the hope that it will be useful, but WITHOUT    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    16 details.    17     18 You should have received a copy of the GNU General Public License along with    19 this program.  If not, see <http://www.gnu.org/licenses/>.    20 """    21     22 from imiptools.content import Handler    23 from imiptools.data import get_address, get_uri, to_part    24 from imiptools.handlers.common import CommonFreebusy    25     26 class ResourceHandler(Handler):    27     28     "Handling mechanisms specific to resources."    29     30     def _record_and_respond(self, handle_for_attendee):    31     32         oa = self.require_organiser_and_attendees()    33         if not oa:    34             return None    35     36         organiser_item, attendees = oa    37     38         # Process each attendee separately.    39     40         calendar = []    41     42         for attendee, attendee_attr in attendees.items():    43     44             # Check for event using UID.    45     46             if not self.have_new_object(attendee):    47                 continue    48     49             # Collect response objects produced when handling the request.    50     51             response = handle_for_attendee(attendee, attendee_attr)    52             if response:    53                 calendar.append(response)    54     55         return calendar    56     57     def _schedule_for_attendee(self, attendee, attendee_attr):    58     59         # If newer than any old version, discard old details from the    60         # free/busy record and check for suitability.    61     62         periods = self.get_periods()    63         freebusy = self.store.get_freebusy(attendee)    64         scheduled = self.can_schedule(freebusy, periods)    65     66         attendee_attr["PARTSTAT"] = scheduled and "ACCEPTED" or "DECLINED"    67         if self.messenger and self.messenger.sender != get_address(attendee):    68             attendee_attr["SENT-BY"] = get_uri(self.messenger.sender)    69     70         # Make a version of the request with just this attendee.    71     72         self.obj["ATTENDEE"] = [(attendee, attendee_attr)]    73     74         # Update the DTSTAMP.    75     76         self.update_dtstamp()    77     78         event = self.obj.to_node()    79         self.store.set_event(attendee, self.uid, event)    80     81         # Only update free/busy details if the event is scheduled.    82     83         if scheduled:    84             self.update_freebusy(freebusy, attendee, periods)    85         else:    86             self.remove_from_freebusy(freebusy, attendee)    87     88         if self.publisher:    89             self.publisher.set_freebusy(attendee, freebusy)    90     91         return event    92     93     def _cancel_for_attendee(self, attendee, attendee_attr):    94     95         freebusy = self.store.get_freebusy(attendee)    96         self.remove_from_freebusy(freebusy, attendee)    97     98         if self.publisher:    99             self.publisher.set_freebusy(attendee, freebusy)   100    101         return None   102    103 class Event(ResourceHandler):   104    105     "An event handler."   106    107     def add(self):   108         pass   109    110     def cancel(self):   111    112         "Cancel attendance for attendees."   113    114         self._record_and_respond(self._cancel_for_attendee)   115    116     def counter(self):   117    118         "Since this handler does not send requests, it will not handle replies."   119    120         pass   121    122     def declinecounter(self):   123    124         """   125         Since this handler does not send counter proposals, it will not handle   126         replies to such proposals.   127         """   128    129         pass   130    131     def publish(self):   132         pass   133    134     def refresh(self):   135         pass   136    137     def reply(self):   138    139         "Since this handler does not send requests, it will not handle replies."   140    141         pass   142    143     def request(self):   144    145         """   146         Respond to a request by preparing a reply containing accept/decline   147         information for each indicated attendee.   148    149         No support for countering requests is implemented.   150         """   151    152         response = self._record_and_respond(self._schedule_for_attendee)   153         if response:   154             self.add_result("REPLY", map(get_address, self.obj.get_values("ORGANIZER")), to_part("REPLY", response))   155    156 class Freebusy(Handler, CommonFreebusy):   157    158     "A free/busy handler."   159    160     def publish(self):   161         pass   162    163     def reply(self):   164    165         "Since this handler does not send requests, it will not handle replies."   166    167         pass   168    169     # request provided by CommonFreeBusy.request   170    171 class Journal(ResourceHandler):   172    173     "A journal entry handler."   174    175     def add(self):   176         pass   177    178     def cancel(self):   179         pass   180    181     def publish(self):   182         pass   183    184 class Todo(ResourceHandler):   185    186     "A to-do item handler."   187    188     def add(self):   189         pass   190    191     def cancel(self):   192         pass   193    194     def counter(self):   195    196         "Since this handler does not send requests, it will not handle replies."   197    198         pass   199    200     def declinecounter(self):   201    202         """   203         Since this handler does not send counter proposals, it will not handle   204         replies to such proposals.   205         """   206    207         pass   208    209     def publish(self):   210         pass   211    212     def refresh(self):   213         pass   214    215     def reply(self):   216    217         "Since this handler does not send requests, it will not handle replies."   218    219         pass   220    221     def request(self):   222         pass   223    224 # Handler registry.   225    226 handlers = [   227     ("VFREEBUSY",   Freebusy),   228     ("VEVENT",      Event),   229     ("VTODO",       Todo),   230     ("VJOURNAL",    Journal),   231     ]   232    233 # vim: tabstop=4 expandtab shiftwidth=4