ebeigarts-ri_cal 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/History.txt +136 -0
  2. data/Manifest.txt +140 -0
  3. data/README.txt +410 -0
  4. data/Rakefile +53 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +1 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal.rb +175 -0
  21. data/lib/ri_cal/component.rb +249 -0
  22. data/lib/ri_cal/component/alarm.rb +21 -0
  23. data/lib/ri_cal/component/calendar.rb +259 -0
  24. data/lib/ri_cal/component/event.rb +60 -0
  25. data/lib/ri_cal/component/freebusy.rb +18 -0
  26. data/lib/ri_cal/component/journal.rb +30 -0
  27. data/lib/ri_cal/component/non_standard.rb +35 -0
  28. data/lib/ri_cal/component/t_z_info_timezone.rb +139 -0
  29. data/lib/ri_cal/component/timezone.rb +197 -0
  30. data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
  31. data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
  32. data/lib/ri_cal/component/timezone/timezone_period.rb +78 -0
  33. data/lib/ri_cal/component/todo.rb +44 -0
  34. data/lib/ri_cal/core_extensions.rb +6 -0
  35. data/lib/ri_cal/core_extensions/array.rb +7 -0
  36. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  37. data/lib/ri_cal/core_extensions/date.rb +13 -0
  38. data/lib/ri_cal/core_extensions/date/conversions.rb +69 -0
  39. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  40. data/lib/ri_cal/core_extensions/date_time/conversions.rb +55 -0
  41. data/lib/ri_cal/core_extensions/object.rb +8 -0
  42. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  43. data/lib/ri_cal/core_extensions/string.rb +8 -0
  44. data/lib/ri_cal/core_extensions/string/conversions.rb +53 -0
  45. data/lib/ri_cal/core_extensions/time.rb +13 -0
  46. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  47. data/lib/ri_cal/core_extensions/time/conversions.rb +42 -0
  48. data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
  49. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +55 -0
  50. data/lib/ri_cal/fast_date_time.rb +226 -0
  51. data/lib/ri_cal/floating_timezone.rb +32 -0
  52. data/lib/ri_cal/invalid_property_value.rb +8 -0
  53. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  54. data/lib/ri_cal/occurrence_enumerator.rb +265 -0
  55. data/lib/ri_cal/occurrence_period.rb +17 -0
  56. data/lib/ri_cal/parser.rb +145 -0
  57. data/lib/ri_cal/properties/alarm.rb +390 -0
  58. data/lib/ri_cal/properties/calendar.rb +164 -0
  59. data/lib/ri_cal/properties/event.rb +1526 -0
  60. data/lib/ri_cal/properties/freebusy.rb +594 -0
  61. data/lib/ri_cal/properties/journal.rb +1240 -0
  62. data/lib/ri_cal/properties/timezone.rb +151 -0
  63. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  64. data/lib/ri_cal/properties/todo.rb +1562 -0
  65. data/lib/ri_cal/property_value.rb +149 -0
  66. data/lib/ri_cal/property_value/array.rb +27 -0
  67. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  68. data/lib/ri_cal/property_value/date.rb +169 -0
  69. data/lib/ri_cal/property_value/date_time.rb +351 -0
  70. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  71. data/lib/ri_cal/property_value/date_time/time_machine.rb +159 -0
  72. data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
  73. data/lib/ri_cal/property_value/duration.rb +110 -0
  74. data/lib/ri_cal/property_value/geo.rb +11 -0
  75. data/lib/ri_cal/property_value/integer.rb +12 -0
  76. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  77. data/lib/ri_cal/property_value/period.rb +86 -0
  78. data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +793 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +60 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  88. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +49 -0
  89. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  90. data/lib/ri_cal/property_value/text.rb +40 -0
  91. data/lib/ri_cal/property_value/uri.rb +11 -0
  92. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  93. data/lib/ri_cal/required_timezones.rb +55 -0
  94. data/performance/paris_eastern/subject.rb +90 -0
  95. data/performance/penultimate_weekday/subject.rb +15 -0
  96. data/performance/psm_big_enum/ical.ics +3171 -0
  97. data/performance/psm_big_enum/subject.rb +16 -0
  98. data/performance/utah_cycling/subject.rb +55 -0
  99. data/ri_cal.gemspec +48 -0
  100. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  101. data/script/benchmark_subject +23 -0
  102. data/script/console +10 -0
  103. data/script/destroy +14 -0
  104. data/script/generate +14 -0
  105. data/script/profile_subject +27 -0
  106. data/script/txt2html +71 -0
  107. data/spec/ri_cal/bugreports_spec.rb +230 -0
  108. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  109. data/spec/ri_cal/component/calendar_spec.rb +88 -0
  110. data/spec/ri_cal/component/event_spec.rb +718 -0
  111. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  112. data/spec/ri_cal/component/journal_spec.rb +37 -0
  113. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +59 -0
  114. data/spec/ri_cal/component/timezone_spec.rb +236 -0
  115. data/spec/ri_cal/component/todo_spec.rb +112 -0
  116. data/spec/ri_cal/component_spec.rb +224 -0
  117. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  118. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  119. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  120. data/spec/ri_cal/fast_date_time_spec.rb +67 -0
  121. data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
  122. data/spec/ri_cal/parser_spec.rb +337 -0
  123. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  124. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  125. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  126. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  127. data/spec/ri_cal/property_value/period_spec.rb +63 -0
  128. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  129. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  130. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  131. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  132. data/spec/ri_cal/property_value_spec.rb +125 -0
  133. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  134. data/spec/ri_cal_spec.rb +53 -0
  135. data/spec/spec.opts +4 -0
  136. data/spec/spec_helper.rb +46 -0
  137. data/tasks/gem_loader/load_active_support.rb +3 -0
  138. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  139. data/tasks/ri_cal.rake +412 -0
  140. data/tasks/spec.rake +102 -0
  141. metadata +230 -0
@@ -0,0 +1,7 @@
1
+ Seconds - Freq="SECONDLY", BYSECOND
2
+ Minutes - Freq="MINUTELY", BYMINUTE
3
+ Hours - Freq="HOURLY", BYHOUR
4
+ Days - Freq="DAILY", BYDAY, BYMONTHDAY, BYYEARDAY
5
+ Weeks - Freq="WEEKLY", BYWEEKNO
6
+ Months - Freq="MONTHLY", BYMONTH
7
+ Years - Freq="YEARLY"
data/docs/rfc2445.pdf ADDED
Binary file
data/lib/ri_cal.rb ADDED
@@ -0,0 +1,175 @@
1
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
2
+ #
3
+ # The RiCal module provides the outermost namespace, along with several convenience methods for parsing
4
+ # and building calendars and calendar components.
5
+ module RiCal
6
+
7
+ require 'stringio'
8
+ require 'rational'
9
+
10
+ my_dir = File.dirname(__FILE__)
11
+
12
+ autoload :Component, "#{my_dir}/ri_cal/component.rb"
13
+ autoload :TimezonePeriod, "#{my_dir}/ri_cal/properties/timezone_period.rb"
14
+ autoload :OccurrenceEnumerator, "#{my_dir}/ri_cal/occurrence_enumerator.rb"
15
+
16
+ # :stopdoc:
17
+ VERSION = '0.8.1'
18
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
19
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
20
+
21
+ # Returns the version string for the library.
22
+ #
23
+ def self.version
24
+ VERSION
25
+ end
26
+
27
+ # Returns the library path for the module. If any arguments are given,
28
+ # they will be joined to the end of the libray path using
29
+ # <tt>File.join</tt>.
30
+ #
31
+ def self.libpath( *args )
32
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
33
+ end
34
+
35
+ # Returns the lpath for the module. If any arguments are given,
36
+ # they will be joined to the end of the path using
37
+ # <tt>File.join</tt>.
38
+ #
39
+ def self.path( *args )
40
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
41
+ end
42
+
43
+ # Utility method used to rquire all files ending in .rb that lie in the
44
+ # directory below this file that has the same name as the filename passed
45
+ # in. Optionally, a specific _directory_ name can be passed in such that
46
+ # the _filename_ does not have to be equivalent to the directory.
47
+ #
48
+ def self.require_all_libs_relative_to( fname, dir = nil )
49
+ dir ||= ::File.basename(fname, '.*')
50
+ search_me = ::File.expand_path(::File.join(::File.dirname(fname), dir, '**', '*.rb'))
51
+ Dir.glob(search_me).sort.each {|rb|
52
+ require rb}
53
+ end
54
+
55
+ # :startdoc:
56
+
57
+ # Parse an io stream and return an array of iCalendar entities.
58
+ # Normally this will be an array of RiCal::Component::Calendar instances
59
+ def self.parse(io)
60
+ Parser.new(io).parse
61
+ end
62
+
63
+ # Parse a string and return an array of iCalendar entities.
64
+ # see RiCal.parse
65
+ def self.parse_string(string)
66
+ parse(StringIO.new(string))
67
+ end
68
+
69
+ def self.debug # :nodoc:
70
+ @debug
71
+ end
72
+
73
+ def self.debug=(val) # :nodoc:
74
+ @debug = val
75
+ end
76
+
77
+ # return a new Alarm event or todo component. If a block is provided it will will be executed in
78
+ # the context of a builder object which can be used to initialize the properties of the
79
+ # new Alarm.
80
+ def self.Alarm(&init_block)
81
+ Component::Alarm.new(&init_block)
82
+ end
83
+
84
+ # return a new Calendar. If a block is provided it will will be executed in
85
+ # the context of a builder object which can be used to initialize the properties and components of the
86
+ # new calendar.
87
+ def self.Calendar(&init_block)
88
+ Component::Calendar.new(&init_block)
89
+ end
90
+
91
+ # return a new Event calendar component. If a block is provided it will will be executed in
92
+ # the context of a builder object which can be used to initialize the properties and alarms of the
93
+ # new Event.
94
+ def self.Event(&init_block)
95
+ Component::Event.new(&init_block)
96
+ end
97
+
98
+ # return a new Freebusy calendar component. If a block is provided it will will be executed in
99
+ # the context of a builder object which can be used to initialize the properties and components of the
100
+ # new Freebusy.
101
+ def self.Freebusy(&init_block)
102
+ Component::Freebusy.new(&init_block)
103
+ end
104
+
105
+ # return a new Journal calendar component. If a block is provided it will will be executed in
106
+ # the context of a builder object which can be used to initialize the properties and components of the
107
+ # new Event.
108
+ def self.Journal(&init_block)
109
+ Component::Journal.new(&init_block)
110
+ end
111
+
112
+ # return a new Timezone calendar component. If a block is provided it will will be executed in
113
+ # the context of a builder object which can be used to initialize the properties and timezone periods of the
114
+ # new Timezone.
115
+ def self.Timezone(&init_block)
116
+ Component::Timezone.new(&init_block)
117
+ end
118
+
119
+ # return a new TimezonePeriod timezone component. If a block is provided it will will be executed in
120
+ # the context of a builder object which can be used to initialize the properties of the
121
+ # new TimezonePeriod.
122
+ def self.TimezonePeriod(&init_block)
123
+ Component::TimezonePeriod.new(&init_block)
124
+ end
125
+
126
+ if Object.const_defined?(:ActiveSupport)
127
+ as = Object.const_get(:ActiveSupport)
128
+ if as.const_defined?(:TimeWithZone)
129
+ time_with_zone = as.const_get(:TimeWithZone)
130
+ end
131
+ end
132
+
133
+ # TimeWithZone will be set to ActiveSupport::TimeWithZone if the activesupport gem is loaded
134
+ # otherwise it will be nil
135
+ TimeWithZone = time_with_zone
136
+
137
+ # return a new Todo calendar component. If a block is provided it will will be executed in
138
+ # the context of a builder object which can be used to initialize the properties and alarms of the
139
+ # new Todo.
140
+ def self.Todo(&init_block)
141
+ Component::Todo.new(&init_block)
142
+ end
143
+
144
+ def self.ro_calls=(value)
145
+ @ro_calls = value
146
+ end
147
+
148
+ def self.ro_calls
149
+ @ro_calls ||= 0
150
+ end
151
+
152
+ def self.ro_misses=(value)
153
+ @ro_misses = value
154
+ end
155
+
156
+ def self.ro_misses
157
+ @ro_misses ||= 0
158
+ end
159
+
160
+ def self.RationalOffset
161
+ self.ro_calls += 1
162
+ @rational_offset ||= Hash.new {|h, seconds|
163
+ self.ro_misses += 1
164
+ h[seconds] = Rational(seconds, 86400)}
165
+ end
166
+
167
+ end # module RiCal
168
+
169
+ (-12..12).each do |hour_offset|
170
+ RiCal.RationalOffset[hour_offset * 86400]
171
+ end
172
+
173
+
174
+ RiCal.require_all_libs_relative_to(__FILE__)
175
+ # EOF
@@ -0,0 +1,249 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
3
+ #
4
+ class Component #:nodoc:
5
+ class ComponentBuilder #:nodoc:
6
+ def initialize(component)
7
+ @component = component
8
+ end
9
+
10
+ def method_missing(selector, *args, &init_block) #:nodoc:
11
+ if(sub_comp_class = @component.subcomponent_class[selector])
12
+ if init_block
13
+ sub_comp = sub_comp_class.new(@component)
14
+ if init_block.arity == 1
15
+ yield ComponentBuilder.new(sub_comp)
16
+ else
17
+ ComponentBuilder.new(sub_comp).instance_eval(&init_block)
18
+ end
19
+ self.add_subcomponent(sub_comp)
20
+ end
21
+ else
22
+ sel = selector.to_s
23
+ sel = "#{sel}=" unless /(^(add_)|(remove_))|(=$)/ =~ sel
24
+ if @component.respond_to?(sel)
25
+ @component.send(sel, *args)
26
+ else
27
+ super
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ autoload :Timezone, "#{File.dirname(__FILE__)}/component/timezone.rb"
34
+
35
+ attr_accessor :imported #:nodoc:
36
+
37
+ def initialize(parent=nil, entity_name = nil, &init_block) #:nodoc:
38
+ @parent = parent
39
+ if block_given?
40
+ if init_block.arity == 1
41
+ init_block.call(ComponentBuilder.new(self))
42
+ else
43
+ ComponentBuilder.new(self).instance_eval(&init_block)
44
+ end
45
+ end
46
+ end
47
+
48
+ def default_tzid #:nodoc:
49
+ if @parent
50
+ @parent.default_tzid
51
+ else
52
+ PropertyValue::DateTime.default_tzid
53
+ end
54
+ end
55
+
56
+ def find_timezone(identifier) #:nodoc:
57
+ if @parent
58
+ @parent.find_timezone(identifier)
59
+ else
60
+ begin
61
+ Calendar::TZInfoWrapper.new(TZInfo::Timezone.get(identifier), self)
62
+ rescue ::TZInfo::InvalidTimezoneIdentifier => ex
63
+ raise RiCal::InvalidTimezoneIdentifier.invalid_tzinfo_identifier(identifier)
64
+ end
65
+ end
66
+ end
67
+
68
+ def tz_info_source?
69
+ if @parent
70
+ @parent.tz_info_source?
71
+ else
72
+ true
73
+ end
74
+ end
75
+
76
+ def time_zone_for(ruby_object) #:nodoc:
77
+ @parent.time_zone_for(ruby_object) #:nodoc:
78
+ end
79
+
80
+ def subcomponent_class #:nodoc:
81
+ {}
82
+ end
83
+
84
+ def self.from_parser(parser, parent, entity_name) #:nodoc:
85
+ entity = self.new(parent, entity_name)
86
+ entity.imported = true
87
+ line = parser.next_separated_line
88
+ while parser.still_in(entity_name, line)
89
+ entity.process_line(parser, line)
90
+ line = parser.next_separated_line
91
+ end
92
+ entity
93
+ end
94
+
95
+ def self.parse(io) #:nodoc:
96
+ Parser.new(io).parse
97
+ end
98
+
99
+ def imported? #:nodoc:
100
+ imported
101
+ end
102
+
103
+ def self.parse_string(string) #:nodoc:
104
+ parse(StringIO.new(string))
105
+ end
106
+
107
+ def subcomponents #:nodoc:
108
+ @subcomponents ||= Hash.new {|h, k| h[k] = []}
109
+ end
110
+
111
+ def entity_name #:nodoc:
112
+ self.class.entity_name
113
+ end
114
+
115
+ # return an array of Alarm components within this component :nodoc:
116
+ # Alarms may be contained within Events, and Todos
117
+ def alarms
118
+ subcomponents["VALARM"]
119
+ end
120
+
121
+ def add_subcomponent(component) #:nodoc:
122
+ subcomponents[component.entity_name] << component
123
+ end
124
+
125
+ def parse_subcomponent(parser, line) #:nodoc:
126
+ subcomponents[line[:value]] << parser.parse_one(line, self)
127
+ end
128
+
129
+ def process_line(parser, line) #:nodoc:
130
+ if line[:name] == "BEGIN"
131
+ parse_subcomponent(parser, line)
132
+ else
133
+ setter = self.class.property_parser[line[:name]]
134
+ if setter
135
+ send(setter, line)
136
+ else
137
+ self.add_x_property(line[:name], PropertyValue::Text.new(self, line))
138
+ end
139
+ end
140
+ end
141
+
142
+ # return a hash of any extended properties, (i.e. those with a property name starting with "X-"
143
+ # representing an extension to the RFC 2445 specification)
144
+ def x_properties
145
+ @x_properties ||= Hash.new {|h,k| h[k] = []}
146
+ end
147
+
148
+ # Add a n extended property
149
+ def add_x_property(name, prop)
150
+ x_properties[name] << prop
151
+ end
152
+
153
+ def method_missing(selector, *args, &b) #:nodoc:
154
+ xprop_candidate = selector.to_s
155
+ if (match = /^x_(.+)(=?)$/.match(xprop_candidate))
156
+ if match[2] == "="
157
+ add_x_property("x_#{match[1]}", *args)
158
+ else
159
+ x_properties[xprop_candidate]
160
+ end
161
+ else
162
+ super
163
+ end
164
+ end
165
+
166
+ # Predicate to determine if the component is valid according to RFC 2445
167
+ def valid?
168
+ !mutual_exclusion_violation
169
+ end
170
+
171
+ def initialize_copy(original) #:nodoc:
172
+ end
173
+
174
+ def prop_string(prop_name, *properties) #:nodoc:
175
+ properties = properties.flatten.compact
176
+ if properties && !properties.empty?
177
+ properties.map {|prop| "#{prop_name}#{prop.to_s}"}.join("\n")
178
+ else
179
+ nil
180
+ end
181
+ end
182
+
183
+ def add_property_date_times_to(required_timezones, property) #:nodoc:
184
+ if property
185
+ if Array === property
186
+ property.each do |prop|
187
+ prop.add_date_times_to(required_timezones)
188
+ end
189
+ else
190
+ property.add_date_times_to(required_timezones)
191
+ end
192
+ end
193
+ end
194
+
195
+ def export_prop_to(export_stream, name, prop) #:nodoc:
196
+ if prop
197
+ string = prop_string(name, prop)
198
+ export_stream.puts(string) if string
199
+ end
200
+ end
201
+
202
+ def export_x_properties_to(export_stream) #:nodoc:
203
+ x_properties.each do |name, props|
204
+ props.each do | prop |
205
+ export_stream.puts("#{name}:#{prop}")
206
+ end
207
+ end
208
+ end
209
+
210
+ def export_subcomponent_to(export_stream, subcomponent) #:nodoc:
211
+ subcomponent.each do |component|
212
+ component.export_to(export_stream)
213
+ end
214
+ end
215
+
216
+ # return a string containing the rfc2445 format of the component
217
+ def to_s
218
+ io = StringIO.new
219
+ export_to(io)
220
+ io.string
221
+ end
222
+
223
+ # Export this component to an export stream
224
+ def export_to(export_stream)
225
+ export_stream.puts("BEGIN:#{entity_name}")
226
+ export_properties_to(export_stream)
227
+ export_x_properties_to(export_stream)
228
+ subcomponents.values.each do |sub|
229
+ export_subcomponent_to(export_stream, sub)
230
+ end
231
+ export_stream.puts("END:#{entity_name}")
232
+ end
233
+
234
+ # Export this single component as an iCalendar component containing only this component and
235
+ # any required additional components (i.e. VTIMEZONES referenced from this component)
236
+ # if stream is nil (the default) then this method will return a string,
237
+ # otherwise stream should be an IO to which the iCalendar file contents will be written
238
+ def export(stream=nil)
239
+ wrapper_calendar = Calendar.new
240
+ wrapper_calendar.add_subcomponent(self)
241
+ wrapper_calendar.export(stream)
242
+ end
243
+ end
244
+ end
245
+
246
+ Dir[File.dirname(__FILE__) + "/component/*.rb"].sort.each do |path|
247
+ filename = File.basename(path)
248
+ require path
249
+ end
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. properties alarm.rb])
2
+
3
+ module RiCal
4
+
5
+ class Component
6
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
7
+ #
8
+ # An Alarm component groups properties defining a reminder or alarm associated with an event or to-do
9
+ # TODO: The Alarm component has complex cardinality restrictions depending on the value of the action property
10
+ # i.e. audio, display, email, and proc alarms, this is currently not checked or enforced
11
+ #
12
+ # to see the property accessing methods for this class see the RiCal::Properties::Alarm module
13
+ class Alarm < Component
14
+ include RiCal::Properties::Alarm
15
+
16
+ def self.entity_name #:nodoc:
17
+ "VALARM"
18
+ end
19
+ end
20
+ end
21
+ end