[Rt-commit] r3538 - in Data-ICal: . lib/Data lib/Data/ICal
lib/Data/ICal/Entry lib/Data/ICal/Entry/Alarm t
glasser at bestpractical.com
glasser at bestpractical.com
Tue Jul 26 22:54:00 EDT 2005
Author: glasser
Date: Tue Jul 26 22:53:59 2005
New Revision: 3538
Added:
Data-ICal/lib/Data/ICal/Entry/Alarm/
Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm
Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm
Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm
Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm
Data-ICal/lib/Data/ICal/Entry/Event.pm
Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm
Data-ICal/lib/Data/ICal/Entry/Journal.pm
Data-ICal/lib/Data/ICal/Entry/TimeZone.pm
Data-ICal/lib/Data/ICal/Entry/Todo.pm
Data-ICal/t/02.linewrap.t
Data-ICal/t/03.unknown-props.t
Data-ICal/t/04.mandatory-props.t
Data-ICal/t/05.prop-params.t
Data-ICal/t/06.prop-bad-quote.t
Removed:
Data-ICal/lib/Data/ICal/Todo.pm
Modified:
Data-ICal/ (props changed)
Data-ICal/Makefile.PL
Data-ICal/README
Data-ICal/lib/Data/ICal.pm
Data-ICal/lib/Data/ICal/Entry.pm
Data-ICal/lib/Data/ICal/Property.pm
Data-ICal/t/00.load.t
Data-ICal/t/01.simplegen.t
Log:
r37849 at tin-foil: glasser | 2005-07-25 22:02:44 -0400
Local branch of Data::ICal
r37850 at tin-foil: glasser | 2005-07-25 22:04:34 -0400
Data::ICal uses Class::Accessor.
r37851 at tin-foil: glasser | 2005-07-25 22:06:05 -0400
Make 00.load.t reference the right package.
r37852 at tin-foil: glasser | 2005-07-25 23:44:17 -0400
Big refactoring/cleanup:
* Todo moved into the Data::ICal::Entry directory (which was sitting there
empty just waiting for some love). (This breaks backwards compatibility.)
* Data::ICal (the entire calendar) made a subclass of Data::ICal::Entry, which
allows a lot of repeated code to be deleted (and will make us happy once we
want to allows alarms to be nested in todos/events), although it's a little
strange naming-wise
* be very explicit about which routines that return strings return trailing
newlines
* lots more pod (now passing pod coverage), and a more explicit test
* Change version from 0.001 to 0.01.
I am tempted to s/Entry/Component/ to be consistent with the standard, although
Entry is a much friendlier name.
r37853 at tin-foil: glasser | 2005-07-26 00:03:15 -0400
Add TODO test cases for the fact that we allow repetitions of required-unique
properties, and the fact that we don't wrap text at 75 characters
r37854 at tin-foil: glasser | 2005-07-26 00:10:09 -0400
Line folding implemented.
r37855 at tin-foil: glasser | 2005-07-26 00:26:30 -0400
Honor *_unique_properties
r37856 at tin-foil: glasser | 2005-07-26 00:30:40 -0400
Make sure that the overriding thing happens even if you use different cases for the keys.
r37857 at tin-foil: glasser | 2005-07-26 00:48:06 -0400
Add Event class.
Also document the relied-on-by-tests fact that add_event returns true (presumably
later we'll add a check to make sure you're only adding things to VCALENDARs, except
for VALARMs which can be added only to VEVENTs and VTODOs)
r37858 at tin-foil: glasser | 2005-07-26 01:16:43 -0400
Add is_property, is_unique, is_mandatory, is_repeatable, and is_optional.
Make add_property warn on unknown properties (and test this).
Add property lists to the main calendar class.
r37859 at tin-foil: glasser | 2005-07-26 01:27:07 -0400
Entry's add_string warns if you're missing any mandatory properties.
r37860 at tin-foil: glasser | 2005-07-26 01:34:04 -0400
Update POD to reflect improvements.
r37863 at tin-foil: glasser | 2005-07-26 11:43:24 -0400
Properties can have parameters.
Allow X- properties
r37864 at tin-foil: glasser | 2005-07-26 11:49:01 -0400
perltidy a la jesse
r37865 at tin-foil: glasser | 2005-07-26 13:23:50 -0400
FreeBusy, Journal, and TimeZones added
r37866 at tin-foil: glasser | 2005-07-26 13:26:58 -0400
Oops, X-arguments snuck into some of the property lists. (and another perltidy run)
r37867 at tin-foil: glasser | 2005-07-26 13:57:50 -0400
Add alarms.
r37868 at tin-foil: glasser | 2005-07-26 14:05:25 -0400
The BNF names of properties were not always exactly the same as the actual names. Eit.
r37869 at tin-foil: glasser | 2005-07-26 14:15:27 -0400
README.
Modified: Data-ICal/Makefile.PL
==============================================================================
--- Data-ICal/Makefile.PL (original)
+++ Data-ICal/Makefile.PL Tue Jul 26 22:53:59 2005
@@ -6,5 +6,6 @@
abstract_from('lib/Data/ICal.pm');
license('perl');
requires('Test::More');
+requires('Class::Accessor');
&WriteAll;
Modified: Data-ICal/README
==============================================================================
--- Data-ICal/README (original)
+++ Data-ICal/README Tue Jul 26 22:53:59 2005
@@ -1,18 +1,7 @@
-Data-ICal- version 0.0.1
+Data-ICal version 0.0.1
-[ REPLACE THIS...
-
- The README is used to introduce the module and provide instructions on
- how to install the module, any machine dependencies it may have (for
- example C compilers and installed libraries) and any other information
- that should be understood before the module is installed.
-
- A README file is required for CPAN modules since CPAN extracts the
- README file from a module distribution so that people browsing the
- archive can use it get an idea of the modules uses. It is usually a
- good idea to provide version information here so that people can
- decide whether fixes for the module are worth downloading.
-]
+Data::ICal is a straightforward generator for iCalendar (RFC 2445) files, such
+as those used in Apple's iCal.
INSTALLATION
Modified: Data-ICal/lib/Data/ICal.pm
==============================================================================
--- Data-ICal/lib/Data/ICal.pm (original)
+++ Data-ICal/lib/Data/ICal.pm Tue Jul 26 22:53:59 2005
@@ -2,187 +2,153 @@
use strict;
package Data::ICal;
-
-our $VERSION = '0.001';
+use base qw/Data::ICal::Entry/;
+our $VERSION = '0.01';
use Carp;
-# Module implementation here
+=head1 NAME
+Data::ICal - Generates iCalendar (RFC 2445) calendar files
-sub new {
- my $class = shift;
- my $self = {};
- bless $self, $class;
- return $self;
-}
+=head1 SYNOPSIS
+ use Data::ICal;
-=head2 add_entry
+ my $calendar = Data::ICal->new();
-=cut
+ my $vtodo = Data::ICal::Entry::Todo->new();
+ $vtodo->add_properties(
+ # ... see Data::ICal::Entry::Todo documentation
+ );
-sub add_entry {
- my $self = shift;
- my $entry = shift;
- push @{$self->{entries}}, $entry;
-}
+ $calendar->add_entry($vtodo);
-=head2 entries
+ print $calendar->as_string;
+
+=head1 DESCRIPTION
-Returns a ref to the array of entries in this Data::ICal object
+A L<Data::ICal> object represents a C<VCALENDAR> object as defined in the
+iCalendar protocol (RFC 2445, MIME type "text/calendar"), as implemented in many
+popular calendaring programs such as Apple's iCal. L<Data::ICal> only provides
+the ability to generate ICal files, not to parse them.
+
+Each L<Data::ICal> object is a collection of "entries", which are objects of a
+subclass of L<Data::ICal::Entry>. The types of entries defined by iCalendar
+(which refers to them as "components") include events, to-do items, journal
+entries, free/busy time indicators, and time zone descriptors; in addition,
+events and to-do items can contain alarm entries. (Currently, L<Data::ICal>
+only implements to-do items and events.)
-=cut
+L<Data::ICal> is a subclass of L<Data::ICal::Entry>; see its manpage for more
+methods applicable to L<Data::ICal>.
-sub entries {
- my $self = shift;
- return $self->{'entries'} || [];
-}
+=head1 METHODS
+=cut
-=head2 as_string
+=head2 new
+Creates a new L<Data::ICal> object; sets its C<VERSION> and C<PRODID> properties
+to "2.0" and the value of the C<product_id> method respectively.
=cut
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->add_properties(
+ version => '2.0',
+ prodid => $self->product_id,
+ );
+ return $self;
+}
-sub as_string {
- my $self = shift;
-
- my $content;
- $content = $self->header();
-
+=head2 ical_entry_type
- foreach my $entry (@{$self->entries}) {
- $content .= $entry->as_string();
- }
+Returns C<VCALENDAR>, its iCalendar entry name.
- $content .= $self->footer() ."\n";
- return($content);
-}
+=cut
+sub ical_entry_type {'VCALENDAR'}
-sub header {
- my $self = shift;
- return join("\n", "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:".$self->product_id) ."\n";
+=head2 product_id
-}
+Returns the product ID used in the calendar's C<PRODID> property; you may
+wish to override this in a subclass for your own application.
-sub footer {
- my $self = shift;
- return "END:VCALENDAR";
-}
+=cut
sub product_id {
my $self = shift;
return "Data::ICal $VERSION";
}
+=head2 mandatory_unique_properties
+According to the iCalendar standard, the following properties must be specified
+exactly one time for a calendar:
-1; # Magic true value required at end of module
-__END__
-
-=head1 NAME
-
-Data::ICal - [One line description of module's purpose here]
-
-
-=head1 SYNOPSIS
-
- use Data::ICal;
-
-=for author to fill in:
- Brief code example(s) here showing commonest usage(s).
- This section will be as far as many users bother reading
- so make it as educational and exeplary as possible.
-
-
-=head1 DESCRIPTION
-
-=for author to fill in:
- Write a full description of the module and its features here.
- Use subsections (=head2, =head3) as appropriate.
-
-
-=head1 INTERFACE
-
-=for author to fill in:
- Write a separate section listing the public components of the modules
- interface. These normally consist of either subroutines that may be
- exported, or methods that may be called on objects belonging to the
- classes provided by the module.
-
-
-=head1 DIAGNOSTICS
-
-=for author to fill in:
- List every single error and warning message that the module can
- generate (even the ones that will "never happen"), with a full
- explanation of each problem, one or more likely causes, and any
- suggested remedies.
+ prodid version
-=over
-
-=item C<< Error message here, perhaps with %s placeholders >>
+=cut
-[Description of error here]
+sub mandatory_unique_properties {
+ qw(
+ prodid version
+ );
+}
-=item C<< Another error message here >>
+=head2 optional_unique_properties
-[Description of error here]
+According to the iCalendar standard, the following properties may be specified
+at most one time for a calendar:
-[Et cetera, et cetera]
+ calscale method
-=back
+=cut
+sub optional_unique_properties {
+ qw(
+ calscale method
+ );
+}
=head1 CONFIGURATION AND ENVIRONMENT
-=for author to fill in:
- A full explanation of any configuration system(s) used by the
- module, including the names and locations of any configuration
- files, and the meaning of any environment variables or properties
- that can be set. These descriptions must also include details of any
- configuration language used.
-
-Data::ICal requires no configuration files or environment variables.
+L<Data::ICal> requires no configuration files or environment variables.
=head1 DEPENDENCIES
-=for author to fill in:
- A list of all the other modules that this module relies upon,
- including any restrictions on versions, and an indication whether
- the module is part of the standard Perl distribution, part of the
- module's distribution, or must be installed separately. ]
-
-None.
+L<Data::ICal> requires L<Class::Accessor>.
=head1 INCOMPATIBILITIES
-=for author to fill in:
- A list of any modules that this module cannot be used in conjunction
- with. This may be due to name conflicts in the interface, or
- competition for system or program resources, or due to internal
- limitations of Perl (for example, many modules that use source code
- filters are mutually incompatible).
-
None reported.
=head1 BUGS AND LIMITATIONS
-=for author to fill in:
- A list of known problems with the module, together with some
- indication Whether they are likely to be fixed in an upcoming
- release. Also a list of restrictions on the features the module
- does provide: data types that cannot be handled, performance issues
- and the circumstances in which they may arise, practical
- limitations on the size of data sets, special cases that are not
- (yet) handled, etc.
+L<Data::ICal> does not support time zone daylight or standard entries, so time zone
+components are basically useless.
+
+While L<Data::ICal> tries to check which properties are required and repeatable, this
+only works in simple cases; it does not check for properties that must either both exist
+or both not exist, or for mutually exclusive properties.
+
+L<Data::ICal> does not check to see if property parameter names are known in
+general or allowed on the particular property.
+
+L<Data::ICal> does not check to see if nested entries are nested properly (alarms in
+todos and events only, everything else in calendars only).
+
+L<Data::ICal> has no automatic support for converting binary data to the appropriate
+encoding and setting the corresponding parameters.
+
+There is no L<Data::ICal::Entry::Alarm> base class.
No bugs have been reported.
@@ -226,3 +192,7 @@
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
+
+=cut
+
+1;
Modified: Data-ICal/lib/Data/ICal/Entry.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry.pm (original)
+++ Data-ICal/lib/Data/ICal/Entry.pm Tue Jul 26 22:53:59 2005
@@ -3,71 +3,389 @@
package Data::ICal::Entry;
use Data::ICal::Property;
+use Carp;
+=head1 NAME
+
+Data::ICal::Entry - Represents an entry in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vtodo = Data::ICal::Entry::Todo->new();
+ $vtodo->add_properties(
+ # ... see Data::ICal::Entry::Todo documentation
+ );
+
+ $calendar->add_entry($vtodo);
+
+ $event->add_entry($alarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry> object represents a single entry in an iCalendar file.
+(Note that the iCalendar RFC refers to entries as "components".) iCalendar
+defines several types of entries, such as events and to-do lists; each of
+these corresponds to a subclass of L<Data::ICal::Entry> (though only to-do
+lists and events are currently implemented). L<Data::ICal::Entry> should be treated
+as an abstract base class -- all objects created should be of its subclasses.
+The entire calendar itself (the L<Data::ICal> object) is also represented
+as a L<Data::ICal::Entry> object.
+
+Each entry has an entry type (such as C<VCALENDAR> or C<VEVENT>), a series
+of "properties", and possibly some sub-entries. (Only the root L<Data::ICal>
+object can have sub-entries, except for alarm entries contained in events and
+to-dos (not yet implemented).)
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new entry object with no properties or sub-entries.
+
+=cut
sub new {
my $class = shift;
- my $self = {};
+ my $self = {
+ properties => {},
+ entries => [],
+ };
bless $self, $class;
return $self;
}
+=head2 as_string
+
+Returns the entry as an appropriately formatted string (with trailing newline).
+
+Properties are returned in alphabetical order, with multiple properties of the same name
+returned in the order added. (Property order is unimportant
+in iCalendar, and this makes testing easier.)
+If any mandatory property is missing, issues a warning.
+
+=cut
sub as_string {
my $self = shift;
- return join( "\n",
- $self->header, ( map { $_->as_string } @{ $self->properties } ),
- $self->footer )
- . "\n";
+ my $output = $self->header;
+
+ for my $name (
+ $self->mandatory_unique_properties,
+ $self->mandatory_repeatable_properties
+ )
+ {
+ carp "Mandatory property for " . ( ref $self ) . " missing: $name"
+ unless $self->properties->{$name}
+ and @{ $self->properties->{$name} };
+ }
+
+ for my $name ( sort keys %{ $self->properties } ) {
+ $output .= $_
+ for map { $_->as_string } @{ $self->properties->{$name} };
+ }
+
+ for my $entry ( @{ $self->entries } ) {
+ $output .= $entry->as_string;
+ }
+ $output .= $self->footer;
+ return $output;
}
+=head2 add_entry $entry
+
+Adds an entry to this entry. (According to the standard, this should only be called
+on either a to-do or event entry with an alarm entry, or on a calendar entry (L<Data::ICal>)
+with a to-do, event, journal, timezone, or free/busy entry.)
+
+Returns true if the entry was successfully added, and false otherwise (perhaps because you
+tried to add an entry of an invalid type, but this check hasn't been implemented yet).
+
+=cut
+
+sub add_entry {
+ my $self = shift;
+ my $entry = shift;
+ push @{ $self->{entries} }, $entry;
+
+ return 1;
+}
+
+=head2 entries
+
+Returns a reference to the array of subentries of this entry.
+
+=cut
+
+sub entries {
+ my $self = shift;
+ return $self->{'entries'};
+}
+
+=head2 properties
+
+Returns a reference to the hash of properties of this entry. The keys are property names and
+the values are array references containing L<Data::ICal::Property> objects.
+
+=cut
+
sub properties {
my $self = shift;
- return $self->{'properties'} || [];
+ return $self->{'properties'};
}
+=head2 add_property $propname => $propval
+
+Creates a new L<Data::ICal::Property> object with name C<$propname> and value
+C<$propval> and adds it to the event.
+
+If the property is not known to exist for that object type and does not begin
+with C<X->, issues a warning.
+
+If the property is known to be unique, replaces the original property.
+
+To specify parameters for the property, let C<$propval> be a two-element array reference
+where the first element is the property value and the second element is a hash reference.
+The keys of the hash are parameter names; the values should be either strings or array references
+of strings, depending on whether the parameter should have one or multiple (to be comma-separated)
+values.
+
+=cut
+
sub add_property {
my $self = shift;
- my $prop = shift;
- my $val = shift;
- push @{$self->{'properties'}}, Data::ICal::Property->new($prop => $val);
+ my $prop = lc shift;
+ my $val = shift;
+
+ unless ( $self->is_property($prop) or $prop =~ /^x-/i ) {
+ carp "Unknown property for " . ( ref $self ) . ": $prop";
+ }
+
+ if ( $self->is_unique($prop) ) {
+
+ # It should be unique, so clear out anything we might have first
+ $self->properties->{$prop} = [];
+ }
+
+ $val = [ $val, {} ] unless ref $val eq 'ARRAY';
+
+ my ( $prop_value, $param_hash ) = @$val;
+
+ push @{ $self->properties->{$prop} },
+ Data::ICal::Property->new( $prop => $prop_value, $param_hash );
}
+=head2 add_properties $propname1 => $propval1, [$propname2 => $propname2, ...]
+
+Convenience function to call C<add_property> several times with a list of properties.
+
+This method is guaranteed to call add C<add_property> on them in the order given, so that
+unique properties given later in the call will take precedence over those given earlier.
+(This is unrelated to the order of properties when the entry is rendered as a string, though.)
+
+Parameters for the properties are specified in the same way as in C<add_property>.
+
+=cut
+
sub add_properties {
my $self = shift;
- my %args = @_;
- while (my ( $prop, $val) = each %args) {
- $self->add_property( $prop => $val);
+
+ if ( @_ % 2 ) {
+ carp "Odd number of elements in add_properties call";
+ return;
+ }
+
+ while (@_) {
+ my $prop = shift;
+ my $val = shift;
+ $self->add_property( $prop => $val );
}
}
+=head2 mandatory_unique_properties
+
+Subclasses should override this method (which returns an empty list by default)
+to provide a list of lower case strings identifying the properties which must appear exactly
+once in the subclass's entry type.
+
+=cut
+
+sub mandatory_unique_properties { () }
+
+=head2 mandatory_repeatable_properties
+
+Subclasses should override this method (which returns an empty list by default)
+to provide a list of lower case strings identifying the properties which must appear at least
+once in the subclass's entry type.
+
+=cut
+
+sub mandatory_repeatable_properties { () }
+
+=head2 optional_unique_properties
+
+Subclasses should override this method (which returns an empty list by default)
+to provide a list of lower case strings identifying the properties which must appear at most
+once in the subclass's entry type.
+
+=cut
+
+sub optional_unique_properties { () }
+
+=head2 optional_repeatable_properties
+
+Subclasses should override this method (which returns an empty list by default)
+to provide a list of lower case strings identifying the properties which may appear zero,
+one, or more times in the subclass's entry type.
+
+=cut
-sub mandatory_unique_properties {
+sub optional_repeatable_properties { () }
+
+=head2 is_property $name
+
+Returns a boolean value indicating whether or not the property C<$name> is known to the class
+(that is, if it's listed in C<(mandatory/optional)_(unique/repeatable)_properties>).
+
+=cut
+
+sub is_property {
+ my $self = shift;
+ my $name = shift;
+ return scalar grep { $_ eq $name } $self->mandatory_unique_properties,
+ $self->mandatory_repeatable_properties,
+ $self->optional_unique_properties,
+ $self->optional_repeatable_properties;
}
-sub mandatory_repeatable_properties {
+=head2 is_mandatory $name
+
+Returns a boolean value indicating whether or not the property C<$name> is known to the class as mandatory
+(that is, if it's listed in C<mandatory_(unique/repeatable)_properties>).
+
+=cut
+
+sub is_mandatory {
+ my $self = shift;
+ my $name = shift;
+ return scalar grep { $_ eq $name } $self->mandatory_unique_properties,
+ $self->mandatory_repeatable_properties;
}
-sub optional_unique_properties {
+=head2 is_optional $name
+
+Returns a boolean value indicating whether or not the property C<$name> is known to the class as optional
+(that is, if it's listed in C<optional_(unique/repeatable)_properties>).
+
+=cut
+
+sub is_optional {
+ my $self = shift;
+ my $name = shift;
+ return scalar grep { $_ eq $name } $self->optional_unique_properties,
+ $self->optional_repeatable_properties;
}
-sub optional_repeatable_properties {
+=head2 is_unique $name
+
+Returns a boolean value indicating whether or not the property C<$name> is known to the class as unique
+(that is, if it's listed in C<(mandatory/optional)_unique_properties>).
+
+=cut
+
+sub is_unique {
+ my $self = shift;
+ my $name = shift;
+ return scalar grep { $_ eq $name } $self->mandatory_unique_properties,
+ $self->optional_unique_properties;
}
-sub ical_entry_type {
- return 'UNDEFINED';
+=head2 is_repeatable $name
+
+Returns a boolean value indicating whether or not the property C<$name> is known to the class as repeatable
+(that is, if it's listed in C<(mandatory/optional)_repeatable_properties>).
+
+=cut
+
+sub is_repeatable {
+ my $self = shift;
+ my $name = shift;
+ return scalar grep { $_ eq $name } $self->mandatory_repeatable_properties,
+ $self->optional_repeatable_properties;
}
+=head2 ical_entry_type
+
+Subclasses should override this method to provide the identifying type name of the entry
+(such as C<VCALENDAR> or C<VTODO>).
+
+=cut
+
+sub ical_entry_type {'UNDEFINED'}
+
+=head2 header
+
+Returns the header line for the entry (including trailing newline).
+
+=cut
+
sub header {
my $self = shift;
- return 'BEGIN:'.$self->ical_entry_type;
+ return 'BEGIN:' . $self->ical_entry_type . "\n";
}
+=head2 footer
+
+Returns the footer line for the entry (including trailing newline).
+
+=cut
+
sub footer {
my $self = shift;
- return 'END:'.$self->ical_entry_type;
+ return 'END:' . $self->ical_entry_type . "\n";
}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
1;
Added: Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,127 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Alarm::Audio;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Alarm::Audio - Represents an audio alarm in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $valarm = Data::ICal::Entry::Alarm::Audio->new();
+ $valarm->add_properties(
+ attach => [ "ftp://host.com/pub/sounds/bell-01.aud", { fmttype => "audio/basic" } ],
+ # Dat*e*::ICal is not a typo here
+ trigger => [ Date::ICal->new( epoch => ... )->ical, { value => 'DATE-TIME' } ],
+ );
+
+ $vevent->add_entry($valarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Alarm::Audio> object represents an audio alarm attached
+to a todo item or event in an iCalendar file. (Note that the iCalendar RFC
+refers to entries as "components".) It is a subclass of L<Data::ICal::Entry>
+and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new L<Data::ICal::Entry::Alarm::Audio> object; sets its C<ACTION> property
+to C<AUDIO>.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->add_property( action => "AUDIO" );
+ return $self;
+}
+
+=head2 ical_entry_type
+
+Returns C<VALARM>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VALARM'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for an audio alarm:
+
+ duration repeat attach
+
+Note that if one of C<duration> or C<repeat> is specified, the other one must be also,
+though this module does not enforce that restriction.
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ duration repeat attach
+ );
+}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the C<trigger> property must be specified
+exactly once for an audio alarm. (In addition, the C<action> property must be
+specified exactly once, but the module automatically sets it for you.)
+
+=cut
+
+sub mandatory_unique_properties {
+ qw(
+ action trigger
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,124 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Alarm::Display;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Alarm::Display - Represents a displayed alarm in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $valarm = Data::ICal::Entry::Alarm::Display->new();
+ $valarm->add_properties(
+ description => "Wake up!",
+ # Dat*e*::ICal is not a typo here
+ trigger => [ Date::ICal->new( epoch => ... )->ical, { value => 'DATE-TIME' } ],
+ );
+
+ $vevent->add_entry($valarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Alarm::Display> object represents a alarm that displays a
+message which is attached to a todo item or event in an iCalendar file. (Note
+that the iCalendar RFC refers to entries as "components".) It is a subclass of
+L<Data::ICal::Entry> and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new L<Data::ICal::Entry::Alarm::Display> object; sets its C<ACTION> property
+to C<DISPLAY>.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->add_property( action => "DISPLAY" );
+ return $self;
+}
+
+=head2 ical_entry_type
+
+Returns C<VALARM>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VALARM'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the C<duration> and C<retreat> properties may be specified
+at most one time for an displayed alarm, and if one is specified, the other one must be also,
+though this module does not enforce that restriction.
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ duration repeat
+ );
+}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the C<trigger> and C<description>
+properties must be specified exactly once for an displayed alarm. (In addition, the
+C<action> property must be specified exactly once, but the module automatically
+sets it for you.)
+
+=cut
+
+sub mandatory_unique_properties {
+ qw(
+ action trigger description
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,156 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Alarm::Email;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Alarm::Email - Represents an emailed alarm in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $valarm = Data::ICal::Entry::Alarm::Audio->new();
+ $valarm->add_properties(
+ attach => [ "basic:ftp://host.com/pub/sounds/bell-01.aud", { fmttype => "audio/basic" } ],
+ # Dat*e*::ICal is not a typo here
+ trigger => [ Date::ICal->new( epoch => ... )->ical, { value => 'DATE-TIME' } ],
+ );
+
+ $vevent->add_entry($valarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Alarm::Email> object represents an emailed alarm attached
+to a todo item or event in an iCalendar file. (Note that the iCalendar RFC
+refers to entries as "components".) It is a subclass of L<Data::ICal::Entry>
+and accepts all of its methods.
+
+The C<attendee> properties are intended as the recipient list of the email; the C<summary>
+as its subject; the C<description> as its body; and the C<attach> as its attachments.
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new L<Data::ICal::Entry::Alarm::Email> object; sets its C<ACTION> property
+to C<EMAIL>.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->add_property( action => "EMAIL" );
+ return $self;
+}
+
+=head2 ical_entry_type
+
+Returns C<VALARM>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VALARM'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the C<duration> and C<retreat> properties may be specified
+at most one time for an emailed alarm, and if one is specified, the other one must be also,
+though this module does not enforce that restriction.
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ duration repeat
+ );
+}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the following properties must be specified
+exactly once for an emailed alarm:
+
+ description summary trigger
+
+In addition, the C<action> property must be specified exactly once, but the
+module automatically sets it for you.
+
+=cut
+
+sub mandatory_unique_properties {
+ qw(
+ action description summary trigger
+ );
+}
+
+=head2 mandatory_repeatable_properties
+
+According to the iCalendar standard, the C<attendee> property must be specified
+at least once for an emailed alarm.
+
+=cut
+
+sub mandatory_repeatable_properties {
+ qw(
+ attendee
+ );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the C<attach> property may be specified
+any number of times for an emailed alarm.
+
+=cut
+
+sub optional_repeatable_properties {
+ qw(
+ attach
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,129 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Alarm::Procedure;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Alarm::Procedure - Represents a procedure-call alarm in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $valarm = Data::ICal::Entry::Alarm::Procedure->new();
+ $valarm->add_properties(
+ attach => [ "ftp://host.com/novo-procs/felizano.exe", { fmttype => "application/binary" } ],
+ # Dat*e*::ICal is not a typo here
+ trigger => [ Date::ICal->new( epoch => ... )->ical, { value => 'DATE-TIME' } ],
+ );
+
+ $vevent->add_entry($valarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Alarm::Procedure> object represents an alarm that calls a
+procedure (in some application-defined way), which is attached to a todo item or
+event in an iCalendar file. (Note that the iCalendar RFC refers to entries as
+"components".) It is a subclass of L<Data::ICal::Entry> and accepts all of its
+methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Creates a new L<Data::ICal::Entry::Alarm::Procedure> object; sets its C<ACTION> property
+to C<PROCEDURE>.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->add_property( action => "PROCEDURE" );
+ return $self;
+}
+
+=head2 ical_entry_type
+
+Returns C<VALARM>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VALARM'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for a procedure-call alarm:
+
+ duration repeat description
+
+Note that if one of C<duration> or C<repeat> is specified, the other one must be also,
+though this module does not enforce that restriction.
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ duration repeat description
+ );
+}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the C<trigger> and C<attach> properties
+must be specified exactly once for a procedure-call alarm. (In addition, the C<action>
+property must be specified exactly once, but the module automatically sets it
+for you.)
+
+=cut
+
+sub mandatory_unique_properties {
+ qw(
+ action trigger attach
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Event.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Event.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,128 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Event;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Event - Represents an event in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vevent = Data::ICal::Entry::Event->new();
+ $vevent->add_properties(
+ summary => "my party",
+ description => "I'll cry if I want to",
+ # Dat*e*::ICal is not a typo here
+ dtstart => Date::ICal->new( epoch => time )->ical,
+ );
+
+ $calendar->add_entry($vevent);
+
+ $vevent->add_entry($alarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Event> object represents a single event in an iCalendar file.
+(Note that the iCalendar RFC refers to entries as "components".) It is a subclass
+of L<Data::ICal::Entry> and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<VEVENT>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VEVENT'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for an event:
+
+ class created description dtstart geo
+ last-modified location organizer priority
+ dtstamp sequence status summary transp
+ uid url recurrence-id
+
+In addition, C<dtend> and C<duration> may be specified at most once each, but not both
+in the same entry (though this restriction is not enforced).
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ class created description dtstart geo
+ last-modified location organizer priority
+ dtstamp sequence status summary transp
+ uid url recurrence-id
+
+ dtend duration
+ );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for an event:
+
+ attach attendee categories comment
+ contact exdate exrule request-status related-to
+ resources rdate rrule
+
+=cut
+
+sub optional_repeatable_properties {
+ qw(
+ attach attendee categories comment
+ contact exdate exrule request-status related-to
+ resources rdate rrule
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,113 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::FreeBusy;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::FreeBusy - Represents blocks of free and busy time in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vfreebusy = Data::ICal::Entry::FreeBusy->new();
+ $vfreebusy->add_properties(
+ organizer => 'MAILTO:jsmith at host.com',
+ # Dat*e*::ICal is not a typo here
+ freebusy => Date::ICal->new( epoch => ... )->ical . '/' . Date::ICal->new( epoch => ... )->ical,
+ );
+
+ $calendar->add_entry($vfreebusy);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::FreeBusy> object represents a request for information about free and
+busy time or a reponse to such a request, in an iCalendar file.
+(Note that the iCalendar RFC refers to entries as "components".) It is a subclass
+of L<Data::ICal::Entry> and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<VFREEBUSY>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VFREEBUSY'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for a free/busy entry:
+
+ contact dtstart dtend duration dtstamp
+ organizer uid url
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ contact dtstart dtend duration dtstamp
+ organizer uid url
+ );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for free/busy entry:
+
+ attendee comment freebusy request-status
+
+=cut
+
+sub optional_repeatable_properties {
+ qw(
+ attendee comment freebusy request-status
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Journal.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Journal.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,119 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Journal;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Journal - Represents a journal entry in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vjournal = Data::ICal::Entry::Journal->new();
+ $vjournal->add_properties(
+ summary => "Minutes of my party",
+ description => "I cried because I wanted to.",
+ # Dat*e*::ICal is not a typo here
+ dtstart => Date::ICal->new( epoch => time )->ical,
+ );
+
+ $calendar->add_entry($vjournal);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Journal> object represents a single journal entry in an iCalendar file.
+(Note that the iCalendar RFC refers to entries as "components".) It is a subclass
+of L<Data::ICal::Entry> and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<VJOURNAL>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VJOURNAL'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for a journal entry:
+
+ class created description dtstart dtstamp
+ last-modified organizer recurrence-id sequence status
+ summary uid url
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ class created description dtstart dtstamp
+ last-modified organizer recurrence-id sequence status
+ summary uid url
+ );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for a journal entry:
+
+ attach attendee categories comment
+ contact exdate exrule related-to rdate
+ rrule request-status
+
+=cut
+
+sub optional_repeatable_properties {
+ qw(
+ attach attendee categories comment
+ contact exdate exrule related-to rdate
+ rrule request-status
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/TimeZone.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/TimeZone.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,115 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::TimeZone;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::TimeZone - Represents a time zone definition in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vtimezone = Data::ICal::Entry::TimeZone->new();
+ $vtimezone->add_properties(
+ tzid => "US-Eastern",
+ tzurl => "http://zones.stds_r_us.net/tz/US-Eastern"
+ );
+
+ $vtimezone->add_entry($daylight); # daylight/ standard not yet implemented
+ $vtimezone->add_entry($standard); # :-(
+
+ $calendar->add_entry($vtimezone);
+
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::TimeZone> object represents the declaration of a time
+zone in an iCalendar file. (Note that the iCalendar RFC refers to entries as
+"components".) It is a subclass of L<Data::ICal::Entry> and accepts all of its
+methods.
+
+This module is not yet useful, because every time zone declaration needs to contain
+at least one C<STANDARD> or C<DAYLIGHT> component, and these have not yet been implemented.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<VTIMEZONE>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VTIMEZONE'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for a time zone declaration:
+
+ last-modified tzurl
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ last-modified tzurl
+ );
+}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the C<tzid> property must be specified
+exact one time in a time zone declaration.
+
+=cut
+
+sub mandatory_unique_properties {
+ qw(
+ tzid
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Added: Data-ICal/lib/Data/ICal/Entry/Todo.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/Todo.pm Tue Jul 26 22:53:59 2005
@@ -0,0 +1,128 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::Todo;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::Todo - Represents a to-do entry in an iCalendar file
+
+
+=head1 SYNOPSIS
+
+ my $vtodo = Data::ICal::Entry::Todo->new();
+ $vtodo->add_properties(
+ summary => "go to sleep",
+ status => 'INCOMPLETE',
+ # Dat*e*::ICal is not a typo here
+ dtstart => Date::ICal->new( epoch => time )->ical,
+ );
+
+ $calendar->add_entry($vtodo);
+
+ $vtodo->add_entry($alarm);
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Entry::Todo> object represents a single to-do entry in an iCalendar file.
+(Note that the iCalendar RFC refers to entries as "components".) It is a subclass
+of L<Data::ICal::Entry> and accepts all of its methods.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<VTODO>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'VTODO'}
+
+=head2 optional_unique_properties
+
+According to the iCalendar standard, the following properties may be specified
+at most one time for a to-do item:
+
+ class completed created description dtstamp
+ dtstart geo last-modified location organizer
+ percent-complete priority recurrence-id sequence status
+ summary uid url
+
+In addition, C<due> and C<duration> may be specified at most once each, but not both
+in the same entry (though this restriction is not enforced).
+
+=cut
+
+sub optional_unique_properties {
+ qw(
+ class completed created description dtstamp
+ dtstart geo last-modified location organizer
+ percent-complete priority recurrence-id sequence status
+ summary uid url
+
+ due duration
+ );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for a to-do item:
+
+ attach attendee categories comment contact
+ exdate exrule request-status related-to resources
+ rdate rrule
+
+=cut
+
+sub optional_repeatable_properties {
+ qw(
+ attach attendee categories comment contact
+ exdate exrule request-status related-to resources
+ rdate rrule
+ );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent C<< <jesse at bestpractical.com> >>
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;
Modified: Data-ICal/lib/Data/ICal/Property.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Property.pm (original)
+++ Data-ICal/lib/Data/ICal/Property.pm Tue Jul 26 22:53:59 2005
@@ -5,22 +5,160 @@
use base qw/Class::Accessor/;
-__PACKAGE__->mk_accessors(qw(key value));
+use Carp;
+
+=head1 NAME
+
+Data::ICal::Property - Represents a property on an entry in an iCalendar file
+
+
+=head1 DESCRIPTION
+
+A L<Data::ICal::Property> object represents a single property on an
+entry in an iCalendar file.
+
+You shouldn't need to access L<Data::ICal::Property> values directly -- just use
+C<add_property> in L<Data::ICal::Entry>.
+
+=head1 METHODS
+
+=cut
+
+=head2 new $key, $value, [$parameter_hash]
+
+Creates a new L<Data::ICal::Property> with key C<$key> and value C<$value>.
+
+If C<$parameter_hash> is provided, sets the property's parameters to it.
+The parameter hash should have keys equal to the names of the parameters (case
+insensitive; parameter hashes should not contain two different keys which are
+the same when converted to upper case); the values should either be a string
+if the parameter has a single value or an array reference of strings if
+the parameter has multiple values.
+
+=cut
sub new {
my $class = shift;
- my $self = {};
-
+ my $self = {};
+
bless $self, $class;
$self->key(shift);
$self->value(shift);
+ $self->parameters( shift || {} );
return ($self);
}
+=head2 key [$key]
+
+Gets or sets the key name of this property.
+
+=head2 value [$value]
+
+Gets or sets the value of this property.
+
+=head2 parameters [$param_hash]
+
+Gets or sets the parameter hash reference of this property.
+
+=cut
+
+__PACKAGE__->mk_accessors(qw(key value parameters));
+
+=head2 as_string
+
+Returns the property formatted as a string (including trailing newline).
+
+=cut
+
sub as_string {
+ my $self = shift;
+ my $string = uc( $self->key )
+ . $self->_parameters_as_string . ":"
+ . $self->value . "\n";
+
+ # Assumption: the only place in an iCalendar that needs folding are property
+ # lines
+ return $self->_fold($string);
+}
+
+=begin private
+
+=head2 _parameters_as_string
+
+Returns the property's parameters as a string. Properties are sorted alphabetically
+to aid testing.
+
+=end private
+
+=cut
+
+sub _parameters_as_string {
my $self = shift;
- return uc($self->key).":".$self->value;
+ my $out = '';
+ for my $name ( sort keys %{ $self->parameters } ) {
+ my $value = $self->parameters->{$name};
+ $out .= ';'
+ . uc($name) . '='
+ . $self->_quoted_parameter_values(
+ ref $value ? @$value : $value );
+ }
+ return $out;
+}
+
+=begin private
+
+=head2 _quoted_parameter_values @values
+
+Quotes any of the values in C<@values> that need to be quoted and returns the quoted values
+joined by commas.
+
+If any of the values contains a double-quote, erases it and emits a warning.
+
+=end private
+
+=cut
+
+sub _quoted_parameter_values {
+ my $self = shift;
+ my @values = @_;
+
+ for my $val (@values) {
+ if ( $val =~ /"/ ) {
+
+ # Get all the way back to the user's code
+ local $Carp::CarpLevel = $Carp::CarpLevel + 1;
+ carp "Invalid parameter value (contains double quote): $val";
+ $val =~ tr/"//d;
+ }
+ }
+
+ return join ',', map { /[;,:]/ ? qq("$_") : $_ } @values;
+}
+
+=begin private
+
+=head2 _fold $string
+
+Returns C<$string> folded with newlines and leading whitespace so that each
+line is at most 75 characters.
+
+(Note that it folds at 75 characters, not 75 bytes as specified in the standard.)
+
+=end private
+
+=cut
+
+sub _fold {
+ my $self = shift;
+ my $string = shift;
+
+ # We can't just use a s//g, because we need to include the added space and
+ # first character of the next line in the count for the next line.
+ while ( $string =~ /(.{76})/ ) {
+ $string =~ s/(.{75})(.)/$1\n $2/;
+ }
+ return $string;
}
1;
Modified: Data-ICal/t/00.load.t
==============================================================================
--- Data-ICal/t/00.load.t (original)
+++ Data-ICal/t/00.load.t Tue Jul 26 22:53:59 2005
@@ -4,4 +4,4 @@
use_ok( 'Data::ICal' );
}
-diag( "Testing Data::ICal $Data::ICal::Generator::VERSION" );
+diag( "Testing Data::ICal $Data::ICal::VERSION" );
Modified: Data-ICal/t/01.simplegen.t
==============================================================================
--- Data-ICal/t/01.simplegen.t (original)
+++ Data-ICal/t/01.simplegen.t Tue Jul 26 22:53:59 2005
@@ -3,28 +3,26 @@
use warnings;
use strict;
-use Test::More tests => 15;
+use Test::More tests => 20;
+use Test::LongString;
+use Test::NoWarnings; # this catches our warnings like setting unknown properties
-use_ok('Data::ICal');
+BEGIN { use_ok('Data::ICal') }
my $s = Data::ICal->new();
isa_ok($s, 'Data::ICal');
-can_ok($s, 'as_string');
+can_ok($s, qw/as_string add_entry entries/);
-can_ok($s, 'add_entry');
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
-
-use_ok('Data::ICal::Todo');
-
-my $todo = Data::ICal::Todo->new();
+my $todo = Data::ICal::Entry::Todo->new();
+isa_ok($todo, 'Data::ICal::Entry::Todo');
isa_ok($todo, 'Data::ICal::Entry');
-can_ok($todo, 'add_property');
-can_ok($todo, 'add_properties');
-can_ok($todo, 'properties');
+can_ok($todo, qw/add_property add_properties properties/);
$todo->add_properties( url => 'http://example.com/todo1',
@@ -41,9 +39,66 @@
is(scalar @{ $s->entries},1);
-my $output = $s->as_string;
-like( $output, qr/^BEGIN:VCALENDAR/, "Starts ok");
-like( $output, qr/END:VCALENDAR/, "Ends ok");
-like($output, qr/BEGIN:VTODO/, "has a single vtodo");
+is_string($s->as_string, <<END_VCAL, "Got the right output");
+BEGIN:VCALENDAR
+PRODID:Data::ICal $Data::ICal::VERSION
+VERSION:2.0
+BEGIN:VTODO
+COMMENT:a first comment
+COMMENT:a second comment
+SUMMARY:This summary trumps the first summary
+URL:http://example.com/todo1
+END:VTODO
+END:VCALENDAR
+END_VCAL
+
+$todo->add_property( suMMaRy => "This one trumps number two, even though weird capitalization!");
+
+is_string($s->as_string, <<END_VCAL, "add_property is case insensitive");
+BEGIN:VCALENDAR
+PRODID:Data::ICal $Data::ICal::VERSION
+VERSION:2.0
+BEGIN:VTODO
+COMMENT:a first comment
+COMMENT:a second comment
+SUMMARY:This one trumps number two, even though weird capitalization!
+URL:http://example.com/todo1
+END:VTODO
+END:VCALENDAR
+END_VCAL
+
+BEGIN { use_ok('Data::ICal::Entry::Event') }
+
+my $event = Data::ICal::Entry::Event->new();
+isa_ok($event, 'Data::ICal::Entry::Event');
+isa_ok($event, 'Data::ICal::Entry');
+
+
+can_ok($event, qw/add_property add_properties properties/);
+
+
+$event->add_properties(
+ summary => 'Awesome party',
+ description => 'at my place!',
+ );
+
+ok($s->add_entry($event));
+is(scalar @{ $s->entries},2);
+is_string($s->as_string, <<END_VCAL, "got the right output");
+BEGIN:VCALENDAR
+PRODID:Data::ICal $Data::ICal::VERSION
+VERSION:2.0
+BEGIN:VTODO
+COMMENT:a first comment
+COMMENT:a second comment
+SUMMARY:This one trumps number two, even though weird capitalization!
+URL:http://example.com/todo1
+END:VTODO
+BEGIN:VEVENT
+DESCRIPTION:at my place!
+SUMMARY:Awesome party
+END:VEVENT
+END:VCALENDAR
+END_VCAL
Added: Data-ICal/t/02.linewrap.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/02.linewrap.t Tue Jul 26 22:53:59 2005
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use Test::More tests => 6;
+use Test::LongString;
+
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
+
+my $todo = Data::ICal::Entry::Todo->new;
+isa_ok($todo, 'Data::ICal::Entry::Todo');
+
+my $hundreds_of_characters = "X" x 300;
+
+is(length $hundreds_of_characters, 300);
+cmp_ok(length $hundreds_of_characters, '>', 75, "the summary is bigger than the suggested line-wrap");
+
+$todo->add_property(summary => $hundreds_of_characters);
+
+lacks_string($todo->as_string, $hundreds_of_characters, "the long string isn't there");
+unlike_string($todo->as_string, qr/.{76}/, "no lines are too long");
Added: Data-ICal/t/03.unknown-props.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/03.unknown-props.t Tue Jul 26 22:53:59 2005
@@ -0,0 +1,31 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use Test::More tests => 6;
+use Test::LongString;
+use Test::Warn;
+
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
+
+my $todo = Data::ICal::Entry::Todo->new();
+isa_ok($todo, 'Data::ICal::Entry::Todo');
+
+warnings_are { $todo->add_property( summary => 'Sum it up.' ) }
+ [], "No warning on real property set";
+
+warnings_are { $todo->add_property( "x-summary" => 'Experimentally sum it up.' ) }
+ [], "No warning on experimental property set";
+
+warning_is { $todo->add_property( summmmary => 'Summmm it up.' ) }
+ {carped => "Unknown property for Data::ICal::Entry::Todo: summmmary"},
+ "Got a warning for fake property set";
+
+is_string($todo->as_string, <<END_VCAL, "Got the right output");
+BEGIN:VTODO
+SUMMARY:Sum it up.
+SUMMMMARY:Summmm it up.
+X-SUMMARY:Experimentally sum it up.
+END:VTODO
+END_VCAL
Added: Data-ICal/t/04.mandatory-props.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/04.mandatory-props.t Tue Jul 26 22:53:59 2005
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use Test::More tests => 6;
+use Test::LongString;
+use Test::Warn;
+
+BEGIN { use_ok('Data::ICal') }
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
+
+my $todo = Data::ICal::Entry::Todo->new;
+isa_ok($todo, 'Data::ICal::Entry::Todo');
+
+my $cal = Data::ICal->new;
+isa_ok($cal, 'Data::ICal');
+
+$cal->add_entry($todo);
+
+# breaking the abstraction, ah well
+$cal->properties->{'prodid'} = [];
+
+my $str;
+
+warning_is { $str = $cal->as_string }
+ {carped => "Mandatory property for Data::ICal missing: prodid"},
+ "Got a warning for missing mandatory property";
+
+is_string($str, <<END_VCAL, "Got the 'right' output anyway");
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VTODO
+END:VTODO
+END:VCALENDAR
+END_VCAL
Added: Data-ICal/t/05.prop-params.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/05.prop-params.t Tue Jul 26 22:53:59 2005
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use Test::More tests => 4;
+use Test::LongString;
+use Test::NoWarnings;
+
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
+
+my $todo = Data::ICal::Entry::Todo->new();
+isa_ok($todo, 'Data::ICal::Entry::Todo');
+
+$todo->add_property( summary => [ 'Sum it up.', { language => "en-US", value => "TEXT" } ] );
+# example from RFC 2445 4.2.11
+$todo->add_properties( attendee => [ 'MAILTO:janedoe at host.com',
+ { member => [ 'MAILTO:projectA at host.com', 'MAILTO:projectB at host.com' ] } ]);
+
+is_string($todo->as_string, <<'END_VCAL', "Got the right output");
+BEGIN:VTODO
+ATTENDEE;MEMBER="MAILTO:projectA at host.com","MAILTO:projectB at host.com":MAILT
+ O:janedoe at host.com
+SUMMARY;LANGUAGE=en-US;VALUE=TEXT:Sum it up.
+END:VTODO
+END_VCAL
Added: Data-ICal/t/06.prop-bad-quote.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/06.prop-bad-quote.t Tue Jul 26 22:53:59 2005
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use Test::More tests => 4;
+use Test::LongString;
+use Test::Warn;
+
+BEGIN { use_ok('Data::ICal::Entry::Todo') }
+
+my $todo = Data::ICal::Entry::Todo->new();
+isa_ok($todo, 'Data::ICal::Entry::Todo');
+
+$todo->add_property( summary => [ 'Sum it up.', { language => 'bla"bla'} ] );
+
+my $str;
+
+warning_like { $str = $todo->as_string }
+ {carped => qr(Invalid parameter value)},
+ "Got a warning for fake property set";
+
+is_string($str, <<END_VCAL, "Got the right output");
+BEGIN:VTODO
+SUMMARY;LANGUAGE=blabla:Sum it up.
+END:VTODO
+END_VCAL
More information about the Rt-commit
mailing list