File Coverage

blib/lib/Net/ICal/Freebusy.pm
Criterion Covered Total %
statement 24 32 75.0
branch 0 8 0.0
condition n/a
subroutine 8 9 88.8
pod 2 2 100.0
total 34 51 66.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # vi:sts=4:shiftwidth=4
3             # -*- Mode: perl -*-
4             #======================================================================
5             #
6             # This package is free software and is provided "as is" without
7             # express or implied warranty. It may be used, redistributed and/or
8             # modified under the same terms as perl itself. ( Either the Artistic
9             # License or the GPL. )
10             #
11             # $Id: Freebusy.pm,v 1.16 2001/08/04 04:59:36 srl Exp $
12             #
13             # (C) COPYRIGHT 2000-2001, Reefknot developers.
14             #
15             # See the AUTHORS file included in the distribution for a full list.
16             #======================================================================
17              
18             =head1 NAME
19              
20             Net::ICal::Freebusy -- Freebusy class
21              
22             =cut
23              
24             package Net::ICal::Freebusy;
25 1     1   5 use strict;
  1         2  
  1         38  
26              
27 1     1   6 use base qw(Net::ICal::Component);
  1         2  
  1         73  
28              
29 1     1   6 use Carp;
  1         3  
  1         60  
30 1     1   5 use Net::ICal::Period;
  1         1  
  1         6  
31 1     1   37 use Net::ICal::Property;
  1         2  
  1         10  
32 1     1   22 use Net::ICal::Util qw(:all);
  1         2  
  1         523  
33              
34             # TODO, BUG 424142: this documentation needs expanding.
35              
36             =head1 DESCRIPTION
37              
38             Net::ICal::Freebusy represents a list of time when someone's
39             free or busy. Freebusy elements can be used in three ways:
40              
41             =over 4
42              
43             =item * To request information about a user's open schedule slots
44              
45             =item * To reply to a request for free/busy information
46              
47             =item * To publish a user's list of free/busy information.
48              
49             =back
50              
51             =head1 SYNOPSIS
52              
53             use Net::ICal::Freebusy;
54              
55             my $p = new Net::ICal::Period("19970101T120000","19970101T123000");
56             my $q = new Net::ICal::Period("19970101T124500","19970101T130000");
57              
58             # syntax which works now
59             my $f = new Net::ICal::Freebusy(freebusy => [$p],
60             organizer => 'alice@wonderland.com');
61              
62             # FIXME, BUG 424144:
63             # you should be able to say this, but it doesn't work now
64             my $f = new Net::ICal::Freebusy(freebusy => [$p, $q],
65             organizer => 'alice@wonderland.com');
66              
67              
68             =head1 BASIC METHODS
69              
70             =head2 new (options_hash)
71              
72             Creates a new Freebusy element. Arguments should be specified
73             as elements in a hash.
74              
75             When making a request for information about a user's free/busy time,
76             arguments can be any of the following:
77              
78             =over 4
79              
80             =item * contact - who to contact about this
81              
82             =item * dtstart - beginning of the window of time we want info about
83              
84             =item * dtend - end of the window of time we want info about.
85              
86             =item * duration - how large a block of time we want to know about.
87              
88             =item * dtstamp - when this request was created
89              
90             =item * organizer - user who wants information about free/busy times
91              
92             =item * uid - a unique identifier for this request.
93              
94             =item * url - a URL with more information about this request
95              
96             =item * attendee - which users' schedules we want info about; an array of Attendee objects
97              
98             =item * comment - a comment about this request.
99              
100             =item * freebusy - allowed but meaningless.
101              
102             =item * request_status - allowed but not relevant.
103              
104             =back
105              
106             When responding to a request for free/busy information, the arguments mean
107             different things:
108              
109             =over 4
110              
111             =item * contact - who to contact about this list
112              
113             =item * dtstart - allowed but irrelevant
114              
115             =item * dtend - allowed but irrelevant
116              
117             =item * duration - allowed but irrelevant
118              
119             =item * dtstamp - when this response was created
120              
121             =item * organizer - allowed but irrelevant
122              
123             =item * uid - a unique identifier for this response.
124              
125             =item * url - a URL with more information about this response.
126              
127             =item * attendee - the user responding to the request
128              
129             =item * comment - a comment about this response.
130              
131             =item * freebusy - an array of Durations that are free. Right now, only one Duration is allowed, This will be fixed.
132              
133             =item * request_status - a number representing the success or failure of the request. See RFC2445 4.8.8.2.
134              
135             =back
136              
137             When publishing information about busy time to other users, the
138             parameters have the following meanings:
139              
140             =over 4
141              
142             =item * contact - who to contact about this list
143              
144             =item * dtstart - Beginning date of this range of published free/busy time
145              
146             =item * dtend - End date of this range of published free/busy time
147              
148             =item * duration - allowed but irrelevant (?)
149              
150             =item * dtstamp - when this information was published
151              
152             =item * organizer - The calendar user associated with this free/busy info
153              
154             =item * uid - a unique identifier for this publication of free/busy info.
155              
156             =item * url - a URL with more information about this published free/busy.
157              
158             =item * attendee - allowed but irrelevant.
159              
160             =item * comment - a comment about this publication.
161              
162             =item * freebusy - an array of Durations that are free. Right now, only one Duration is allowed, This will be fixed.
163              
164             =item * request_status - allowed but irrelevant.
165              
166             =back
167              
168             =begin testing
169              
170             use Net::ICal::Attendee;
171             use Net::ICal::Freebusy;
172              
173             my $f = Net::ICal::Freebusy->new();
174             ok(!defined($f), "new() with no arguments fails");
175              
176             # TODO: add tests and make the first test pass.
177             # That probably means adding in some real validation in the code.
178              
179             my $p = new Net::ICal::Period("19970101T120000","19970101T123000");
180              
181             # NOTE: this test should be compared to FreebusyItem to make sure it's sane.
182             # I'm not at all sure it is. --srl
183              
184             $f = Net::ICal::Freebusy->new(freebusy => [$p],
185             organizer => Net::ICal::Attendee->new('mailto:alice@wonderland.com'));
186             ok(defined($f), "new() with 1 fbitem and an organizer succeeds");
187              
188             my $f_ical = $f->as_ical;
189              
190             my $f2 = Net::ICal::Freebusy->new_from_ical($f_ical);
191              
192             ok($f2->as_ical eq $f->as_ical,
193             'reading in our output results in an identical object');
194              
195             =end testing
196              
197             =cut
198              
199             #============================================================================
200             sub new {
201 0     0 1 0 my ($class, %args) = @_;
202              
203             # set FBTYPE to the default, BUSY, if not otherwise specified.
204             # commented out because this property is supposed to show up on
205             # FREEBUSY lines
206              
207             #unless (defined $args{fbtype}) {
208             # $args{fbtype} = 'BUSY';
209             #}
210              
211 0 0       0 return undef unless (%args);
212              
213 0         0 my $self = &_create ($class, %args);
214              
215 0 0       0 return undef unless (defined $self);
216              
217 0 0       0 unless ($self->uid) {
218 0         0 $self->uid (create_uuid);
219             }
220 0 0       0 return undef unless ($self->validate);
221              
222 0         0 return $self;
223             }
224              
225             #=================================================================================
226             =head2 new_from_ical ($text)
227              
228             Takes iCalendar text as a parameter; returns a Net::ICal::Freebusy object.
229              
230             =cut
231              
232             # new_from_ical is inherited from Net::ICal::Component.
233             # TODO, BUG 424143: this needs a test case done to prove that it works.
234              
235              
236             #==================================================================================
237             # make sure that this object has the bare minimum requirements specified by the RFC,
238             my $count = 0;
239              
240             sub validate {
241 1     1 1 3 my ($self) = @_;
242            
243             #TODO: fill in validation checks
244             #BUG: 424137
245            
246 1         8 return $self->SUPER::validate ($self);
247             }
248              
249             # an internal function that sets up the object.
250             sub _create {
251 1     1   4 my ($class, %args) = @_;
252              
253 1         35 my $map = { # RFC2445 4.6.4 describes VFREEBUSY
254             attendee => { # RFC2445 4.8.4.1 says this is PROHIBITED in VFREEBUSY;
255             # 4.6.4 says it's optional.
256             type => 'parameter',
257             doc => 'who is coming to this meeting',
258             domain => 'ref',
259             options => 'ARRAY',
260             value => undef,
261             },
262             comment => { # RFC2445 4.8.1.4 - optional in VFREEBUSY
263             type => 'parameter',
264             doc => '',
265             domain => 'param',
266             options => [qw(altrep param)],
267             # FIXME, BUG 424124:
268             # there can be more than one of these in an event/todo/journal.
269             # do they need to be ordered in an array?
270             value => undef,
271             },
272             contact => { # RFC2445 4.8.4.2 - optional in VFREEBUSY
273             type => 'parameter',
274             doc => 'who to contact about this event',
275             # i'm really surprised this isn't an Attendee type. but i guess
276             # it makes sense.
277             value => undef,
278             },
279             dtstart => { # RFC2445 4.8.2.4 - optional in VFREEBUSY,
280             type => 'parameter',
281             doc => '',
282             domain => 'ref',
283             # TODO, BUG 424114: needs to be in UTC. how to enforce?
284             options => 'Net::ICal::Time',
285             value => undef,
286             },
287             dtend => { # RFC2445 4.8.2.2 - optional in VFREEBUSY
288             type => 'parameter',
289             doc => 'when this event ends',
290             domain => 'ref',
291             options => 'Net::ICal::Time',
292             value => undef,
293             },
294             duration => { # XXX: RFC2445 4.8.2.5 says nothing about this;
295             # 4.6.4's ABNF says that duration is relevant in VFREEBUSY. Who's right?
296             type => 'parameter',
297             doc => 'how long this task lasts',
298             domain => 'ref',
299             options => 'Net::ICal::Duration',
300             value => undef,
301             },
302             dtstamp => { # RFC2445 4.8.7.2 - REQUIRED in VFREEBUSY
303             # XXX: 4.6.4's ABNF says this is optional. hm?
304             type => 'parameter',
305             doc => '',
306             domain => 'ref',
307             options => 'Net::ICal::Time',
308             value => undef,
309             # TODO, BUG 424118:
310             # This is the date/time this object was created; should we
311             # set it by default if the user doesn't set it?
312             # Does this have to be in UTC?
313             },
314             freebusy => {
315             type => 'parameter',
316             doc => 'one or more Net::ICal::Periods',
317             domain => 'ref',
318             options => 'ARRAY',
319             # TODO, BUG 424144:
320             # we need to support multiple FREEBUSY lines, as well as multiple
321             # Periods inside each FREEBUSY line. This very well might be an array
322             # of Net::ICal::FreebusyItem objects or something. Thoughts?
323             # TODO, BUG 424145: we need to be able to output lines like:
324             # FREEBUSY;VALUE=PERIOD:19971015T050000Z/PT8H30M,19971015T160000Z/PT5H30M
325             },
326             organizer => { # RFC2445 4.8.4.3 - REQUIRED in VFREEBUSY
327             # XXX: 4.6.4's ABNF says this is OPTIONAL. hm?
328             type => 'parameter',
329             doc => '',
330             domain => 'ref',
331             options => 'Net::ICal::Attendee',
332             value => undef,
333             },
334             request_status => { # RFC2445 4.8.8.2 - optional in VFREEBUSY
335             type => 'parameter',
336             doc => 'how successful have we been at scheduling this',
337             value => undef,
338             # This is a varying-granularity field; read the RFC.
339             # 1.x = preliminary success, pending completion
340             # 2.x = request completed successfully, possibly with a fallback.
341             # 3.x = request failed, syntax or semantic error in client req format
342             # 4.x = scheduling error; some kind of failure in the scheduling system.
343             # Values can look like "x.y.z" to give even more granularity.
344             # TODO, BUG 424125: I think we have to define our own error subcodes. --srl
345             },
346             uid => { # RFC2445 4.8.4.7 - REQUIRED in VFREEBUSY
347             # XXX: 4.6.4 claims this is optional. ????
348             type => 'parameter',
349             doc => 'global-unique identifier for a generated event',
350             value => undef,
351             },
352             url => { # RFC2445 4.8.4.6 - optional 1x in VFREEBUSY.
353             type => 'parameter',
354             doc => 'a url associated with this event',
355             value => undef,
356             },
357              
358             };
359              
360 1         12 my $self = $class->SUPER::new ('VFREEBUSY', $map, %args);
361              
362 1         6 return $self;
363             }
364              
365             # TODO, BUG 424148:
366             # Food for thought, from RFC2445 4.6.4:
367             # When present in a "VFREEBUSY" calendar component, the "DTSTART" and
368             # "DTEND" properties SHOULD be specified prior to any "FREEBUSY"
369             # properties. In a free time request, these properties can be used in
370             # combination with the "DURATION" property to represent a request for a
371             # duration of free time within a specified window of time.
372             #
373             # as_ical methods currently don't let us specify the output order. They'll
374             # need to in order for us to be RFC-compliant here.
375              
376             1;
377              
378             =head1 SEE ALSO
379              
380             More documentation pointers can be found in L.
381              
382             =cut