ri_cal 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. data/History.txt +45 -0
  2. data/Manifest.txt +129 -0
  3. data/README.txt +394 -0
  4. data/Rakefile +31 -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 +144 -0
  21. data/lib/ri_cal/component.rb +247 -0
  22. data/lib/ri_cal/component/alarm.rb +21 -0
  23. data/lib/ri_cal/component/calendar.rb +219 -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/t_z_info_timezone.rb +123 -0
  28. data/lib/ri_cal/component/timezone.rb +196 -0
  29. data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
  30. data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
  31. data/lib/ri_cal/component/timezone/timezone_period.rb +53 -0
  32. data/lib/ri_cal/component/todo.rb +43 -0
  33. data/lib/ri_cal/core_extensions.rb +6 -0
  34. data/lib/ri_cal/core_extensions/array.rb +7 -0
  35. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  36. data/lib/ri_cal/core_extensions/date.rb +13 -0
  37. data/lib/ri_cal/core_extensions/date/conversions.rb +61 -0
  38. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  39. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  40. data/lib/ri_cal/core_extensions/object.rb +8 -0
  41. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  42. data/lib/ri_cal/core_extensions/string.rb +8 -0
  43. data/lib/ri_cal/core_extensions/string/conversions.rb +63 -0
  44. data/lib/ri_cal/core_extensions/time.rb +13 -0
  45. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  46. data/lib/ri_cal/core_extensions/time/conversions.rb +61 -0
  47. data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
  48. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  49. data/lib/ri_cal/floating_timezone.rb +32 -0
  50. data/lib/ri_cal/invalid_property_value.rb +8 -0
  51. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  52. data/lib/ri_cal/occurrence_enumerator.rb +206 -0
  53. data/lib/ri_cal/occurrence_period.rb +17 -0
  54. data/lib/ri_cal/parser.rb +138 -0
  55. data/lib/ri_cal/properties/alarm.rb +390 -0
  56. data/lib/ri_cal/properties/calendar.rb +164 -0
  57. data/lib/ri_cal/properties/event.rb +1526 -0
  58. data/lib/ri_cal/properties/freebusy.rb +594 -0
  59. data/lib/ri_cal/properties/journal.rb +1240 -0
  60. data/lib/ri_cal/properties/timezone.rb +151 -0
  61. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  62. data/lib/ri_cal/properties/todo.rb +1562 -0
  63. data/lib/ri_cal/property_value.rb +149 -0
  64. data/lib/ri_cal/property_value/array.rb +27 -0
  65. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  66. data/lib/ri_cal/property_value/date.rb +175 -0
  67. data/lib/ri_cal/property_value/date_time.rb +335 -0
  68. data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
  69. data/lib/ri_cal/property_value/date_time/time_machine.rb +181 -0
  70. data/lib/ri_cal/property_value/date_time/timezone_support.rb +96 -0
  71. data/lib/ri_cal/property_value/duration.rb +110 -0
  72. data/lib/ri_cal/property_value/geo.rb +11 -0
  73. data/lib/ri_cal/property_value/integer.rb +12 -0
  74. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  75. data/lib/ri_cal/property_value/period.rb +82 -0
  76. data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
  81. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
  82. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +793 -0
  83. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  84. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +60 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +49 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  88. data/lib/ri_cal/property_value/text.rb +40 -0
  89. data/lib/ri_cal/property_value/uri.rb +11 -0
  90. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  91. data/lib/ri_cal/required_timezones.rb +55 -0
  92. data/ri_cal.gemspec +49 -0
  93. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  94. data/script/console +10 -0
  95. data/script/destroy +14 -0
  96. data/script/generate +14 -0
  97. data/script/txt2html +71 -0
  98. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  99. data/spec/ri_cal/component/calendar_spec.rb +54 -0
  100. data/spec/ri_cal/component/event_spec.rb +601 -0
  101. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  102. data/spec/ri_cal/component/journal_spec.rb +37 -0
  103. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +36 -0
  104. data/spec/ri_cal/component/timezone_spec.rb +218 -0
  105. data/spec/ri_cal/component/todo_spec.rb +112 -0
  106. data/spec/ri_cal/component_spec.rb +224 -0
  107. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  108. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  109. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  110. data/spec/ri_cal/occurrence_enumerator_spec.rb +573 -0
  111. data/spec/ri_cal/parser_spec.rb +303 -0
  112. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  113. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  114. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  115. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  116. data/spec/ri_cal/property_value/period_spec.rb +49 -0
  117. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  118. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  119. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  120. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  121. data/spec/ri_cal/property_value_spec.rb +125 -0
  122. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  123. data/spec/ri_cal_spec.rb +53 -0
  124. data/spec/spec.opts +4 -0
  125. data/spec/spec_helper.rb +46 -0
  126. data/tasks/gem_loader/load_active_support.rb +3 -0
  127. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  128. data/tasks/ri_cal.rake +410 -0
  129. data/tasks/spec.rake +50 -0
  130. metadata +221 -0
@@ -0,0 +1,17 @@
1
+ module RiCal
2
+ class OccurrencePeriod
3
+ attr_reader :dtstart, :dtend
4
+ def initialize(dtstart, dtend)
5
+ @dtstart = dtstart
6
+ @dtend = dtend
7
+ end
8
+
9
+ def to_s
10
+ "op:#{dtstart}-#{dtend}"
11
+ end
12
+
13
+ def <=>(other)
14
+ [dtstart, dtend] <=> [other.dtstart, other.dtend]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,138 @@
1
+ module RiCal
2
+ #- ©2009 Rick DeNatale
3
+ #- All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ class Parser # :nodoc:
6
+ def next_line #:nodoc:
7
+ result = nil
8
+ begin
9
+ result = buffer_or_line
10
+ @buffer = nil
11
+ while /^\s/ =~ buffer_or_line
12
+ result = "#{result}#{@buffer[1..-1]}"
13
+ @buffer = nil
14
+ end
15
+ rescue EOFError
16
+ return nil
17
+ ensure
18
+ return result
19
+ end
20
+ end
21
+
22
+ def self.parse_params(string) #:nodoc:
23
+ if string
24
+ string.split(";").inject({}) { |result, val|
25
+ m = /^(.+)=(.+)$/.match(val)
26
+ invalid unless m
27
+ result[m[1]] = m[2]
28
+ result
29
+ }
30
+ else
31
+ nil
32
+ end
33
+ end
34
+
35
+ def self.params_and_value(string, optional_initial_semi = false) #:nodoc:
36
+ string = string.sub(/^:/,'')
37
+ return [{}, string] unless optional_initial_semi || string.match(/^;/)
38
+ segments = string.sub(';','').split(":")
39
+ return [{}, string] if segments.length < 2
40
+ quote_count = 0
41
+ gathering_params = true
42
+ params = []
43
+ values = []
44
+ segments.each do |segment|
45
+ if gathering_params
46
+ params << segment
47
+ quote_count += segment.count("\"")
48
+ gathering_params = (1 == quote_count % 2)
49
+ else
50
+ values << segment
51
+ end
52
+ end
53
+ [parse_params(params.join(":")), values.join(":")]
54
+ end
55
+
56
+ def separate_line(string) #:nodoc:
57
+ match = string.match(/^([^;:]*)(.*)$/)
58
+ name = match[1]
59
+ params, value = *Parser.params_and_value(match[2])
60
+ {
61
+ :name => name,
62
+ :params => params,
63
+ :value => value
64
+ }
65
+ end
66
+
67
+ def next_separated_line #:nodoc:
68
+ line = next_line
69
+ line ? separate_line(line) : nil
70
+ end
71
+
72
+ def buffer_or_line #:nodoc:
73
+ @buffer ||= @io.readline.chomp
74
+ end
75
+
76
+ def initialize(io = StringIO.new("")) #:nodoc:
77
+ @io = io
78
+ end
79
+
80
+ def self.parse(io = StringIO.new("")) #:nodoc:
81
+ new(io).parse
82
+ end
83
+
84
+ def invalid #:nodoc:
85
+ raise Exception.new("Invalid icalendar file")
86
+ end
87
+
88
+ def still_in(component, separated_line) #:nodoc:
89
+ invalid unless separated_line
90
+ separated_line[:value] != component || separated_line[:name] != "END"
91
+ end
92
+
93
+ def parse #:nodoc:
94
+ result = []
95
+ while start_line = next_line
96
+ @parent_stack = []
97
+ result << parse_one(start_line, nil)
98
+ end
99
+ result
100
+ end
101
+
102
+ # TODO: Need to parse non-standard component types (iana-token or x-name)
103
+ def parse_one(start, parent_component) #:nodoc:
104
+
105
+ @parent_stack << parent_component
106
+ if Hash === start
107
+ first_line = start
108
+ else
109
+ first_line = separate_line(start)
110
+ end
111
+ invalid unless first_line[:name] == "BEGIN"
112
+ result = case first_line[:value]
113
+ when "VCALENDAR"
114
+ RiCal::Component::Calendar.from_parser(self, parent_component)
115
+ when "VEVENT"
116
+ RiCal::Component::Event.from_parser(self, parent_component)
117
+ when "VTODO"
118
+ RiCal::Component::Todo.from_parser(self, parent_component)
119
+ when "VJOURNAL"
120
+ RiCal::Component::Journal.from_parser(self, parent_component)
121
+ when "VFREEBUSY"
122
+ RiCal::Component::Freebusy.from_parser(self, parent_component)
123
+ when "VTIMEZONE"
124
+ RiCal::Component::Timezone.from_parser(self, parent_component)
125
+ when "VALARM"
126
+ RiCal::Component::Alarm.from_parser(self, parent_component)
127
+ when "DAYLIGHT"
128
+ RiCal::Component::Timezone::DaylightPeriod.from_parser(self, parent_component)
129
+ when "STANDARD"
130
+ RiCal::Component::Timezone::StandardPeriod.from_parser(self, parent_component)
131
+ else
132
+ invalid
133
+ end
134
+ @parent_stack.pop
135
+ result
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,390 @@
1
+ module RiCal
2
+ module Properties #:nodoc:
3
+ #- ©2009 Rick DeNatale
4
+ #- All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # Properties::Alarm provides property accessing methods for the Alarm class
7
+ # This source file is generated by the rical:gen_propmodules rake tasks, DO NOT EDIT
8
+ module Alarm
9
+
10
+ # return the the ACTION property
11
+ # which will be an instances of RiCal::PropertyValueText
12
+ #
13
+ # [purpose (from RFC 2445)]
14
+ # This property defines the action to be invoked when an alarm is triggered
15
+ #
16
+ # see RFC 2445 4.8.6.1 p 126
17
+ def action_property
18
+ @action_property
19
+ end
20
+
21
+ # set the ACTION property
22
+ # property value should be an instance of RiCal::PropertyValueText
23
+ def action_property=(property_value)
24
+ @action_property = property_value
25
+ end
26
+
27
+ # set the value of the ACTION property
28
+ def action=(ruby_value)
29
+ self.action_property= RiCal::PropertyValue::Text.convert(self, ruby_value)
30
+ end
31
+
32
+ # return the value of the ACTION property
33
+ # which will be an instance of String
34
+ def action
35
+ action_property ? action_property.ruby_value : nil
36
+ end
37
+
38
+ def action_property_from_string(line) # :nodoc:
39
+ @action_property = RiCal::PropertyValue::Text.new(self, line)
40
+ end
41
+
42
+
43
+ # return the the DESCRIPTION property
44
+ # which will be an instances of RiCal::PropertyValueText
45
+ #
46
+ # [purpose (from RFC 2445)]
47
+ # This property provides a more complete description of the calendar component, than that provided by the "SUMMARY" property.
48
+ #
49
+ # see RFC 2445 4.8.1.5 pp 81-82
50
+ def description_property
51
+ @description_property
52
+ end
53
+
54
+ # set the DESCRIPTION property
55
+ # property value should be an instance of RiCal::PropertyValueText
56
+ def description_property=(property_value)
57
+ @description_property = property_value
58
+ end
59
+
60
+ # set the value of the DESCRIPTION property
61
+ def description=(ruby_value)
62
+ self.description_property= RiCal::PropertyValue::Text.convert(self, ruby_value)
63
+ end
64
+
65
+ # return the value of the DESCRIPTION property
66
+ # which will be an instance of String
67
+ def description
68
+ description_property ? description_property.ruby_value : nil
69
+ end
70
+
71
+ def description_property_from_string(line) # :nodoc:
72
+ @description_property = RiCal::PropertyValue::Text.new(self, line)
73
+ end
74
+
75
+
76
+ # return the the TRIGGER property
77
+ # which will be an instances of RiCal::PropertyValueduration_or_utc_date_time
78
+ #
79
+ # [purpose (from RFC 2445)]
80
+ # This property specifies when an alarm will trigger.
81
+ #
82
+ # see RFC 2445 4.8.6.3 p 127-129
83
+ def trigger_property
84
+ @trigger_property
85
+ end
86
+
87
+ # set the TRIGGER property
88
+ # property value should be an instance of RiCal::PropertyValueduration_or_utc_date_time
89
+ def trigger_property=(property_value)
90
+ @trigger_property = property_value
91
+ end
92
+
93
+ # set the value of the TRIGGER property
94
+ def trigger=(ruby_value)
95
+ self.trigger_property= RiCal::PropertyValue::duration_or_utc_date_time.convert(self, ruby_value)
96
+ end
97
+
98
+ # return the value of the TRIGGER property
99
+ # which will be an instance of duration_or_utc_date_time
100
+ def trigger
101
+ trigger_property ? trigger_property.ruby_value : nil
102
+ end
103
+
104
+ def trigger_property_from_string(line) # :nodoc:
105
+ @trigger_property = RiCal::PropertyValue::duration_or_utc_date_time.new(self, line)
106
+ end
107
+
108
+
109
+ # return the the DURATION property
110
+ # which will be an instances of RiCal::PropertyValueDuration
111
+ #
112
+ # [purpose (from RFC 2445)]
113
+ # This property specifies a positive duration of time.
114
+ #
115
+ # see RFC 2445 4.8.2.5 pp 94-95
116
+ def duration_property
117
+ @duration_property
118
+ end
119
+
120
+ # set the DURATION property
121
+ # property value should be an instance of RiCal::PropertyValueDuration
122
+ def duration_property=(property_value)
123
+ @duration_property = property_value
124
+ end
125
+
126
+ # set the value of the DURATION property
127
+ def duration=(ruby_value)
128
+ self.duration_property= RiCal::PropertyValue::Duration.convert(self, ruby_value)
129
+ end
130
+
131
+ # return the value of the DURATION property
132
+ # which will be an instance of Duration
133
+ def duration
134
+ duration_property ? duration_property.ruby_value : nil
135
+ end
136
+
137
+ def duration_property_from_string(line) # :nodoc:
138
+ @duration_property = RiCal::PropertyValue::Duration.new(self, line)
139
+ end
140
+
141
+
142
+ # return the the REPEAT property
143
+ # which will be an instances of RiCal::PropertyValueInteger
144
+ #
145
+ # [purpose (from RFC 2445)]
146
+ # This property defines the number of times the alarm should be repeated, after the initial trigger.
147
+ #
148
+ # see RFC 2445 4.8.6.2 p 126-127
149
+ def repeat_property
150
+ @repeat_property
151
+ end
152
+
153
+ # set the REPEAT property
154
+ # property value should be an instance of RiCal::PropertyValueInteger
155
+ def repeat_property=(property_value)
156
+ @repeat_property = property_value
157
+ end
158
+
159
+ # set the value of the REPEAT property
160
+ def repeat=(ruby_value)
161
+ self.repeat_property= RiCal::PropertyValue::Integer.convert(self, ruby_value)
162
+ end
163
+
164
+ # return the value of the REPEAT property
165
+ # which will be an instance of Integer
166
+ def repeat
167
+ repeat_property ? repeat_property.ruby_value : nil
168
+ end
169
+
170
+ def repeat_property_from_string(line) # :nodoc:
171
+ @repeat_property = RiCal::PropertyValue::Integer.new(self, line)
172
+ end
173
+
174
+
175
+ # return the the SUMMARY property
176
+ # which will be an instances of RiCal::PropertyValueText
177
+ #
178
+ # [purpose (from RFC 2445)]
179
+ # This property defines a short summary or subject for the calendar component.
180
+ #
181
+ # see RFC 2445 4.8.1.12 pp 89-90
182
+ def summary_property
183
+ @summary_property
184
+ end
185
+
186
+ # set the SUMMARY property
187
+ # property value should be an instance of RiCal::PropertyValueText
188
+ def summary_property=(property_value)
189
+ @summary_property = property_value
190
+ end
191
+
192
+ # set the value of the SUMMARY property
193
+ def summary=(ruby_value)
194
+ self.summary_property= RiCal::PropertyValue::Text.convert(self, ruby_value)
195
+ end
196
+
197
+ # return the value of the SUMMARY property
198
+ # which will be an instance of String
199
+ def summary
200
+ summary_property ? summary_property.ruby_value : nil
201
+ end
202
+
203
+ def summary_property_from_string(line) # :nodoc:
204
+ @summary_property = RiCal::PropertyValue::Text.new(self, line)
205
+ end
206
+
207
+
208
+ # return the the ATTENDEE property
209
+ # which will be an array of instances of RiCal::PropertyValueCalAddress
210
+ #
211
+ # [purpose (from RFC 2445)]
212
+ # The property defines an 'Attendee' within a calendar component.
213
+ #
214
+ # see RFC 2445 4.8.4.1 pp 102-104
215
+ def attendee_property
216
+ @attendee_property ||= []
217
+ end
218
+
219
+ # set the the ATTENDEE property
220
+ # one or more instances of RiCal::PropertyValueCalAddress may be passed to this method
221
+ def attendee_property=(*property_values)
222
+ @attendee_property= property_values
223
+ end
224
+
225
+ # set the value of the ATTENDEE property to multiple values
226
+ # one or more instances of CalAddress may be passed to this method
227
+ def attendees=(ruby_values)
228
+ @attendee_property = ruby_values.map {|val| RiCal::PropertyValue::CalAddress.convert(self, val)}
229
+ end
230
+
231
+ # set the value of the ATTENDEE property to a single value
232
+ # one instance of CalAddress may be passed to this method
233
+ def attendee=(ruby_value)
234
+ @attendee_property = [RiCal::PropertyValue::CalAddress.convert(self, ruby_value)]
235
+ end
236
+
237
+ # add one or more values to the ATTENDEE property
238
+ # one or more instances of CalAddress may be passed to this method
239
+ def add_attendees(*ruby_values)
240
+ ruby_values.each {|val| self.attendee_property << RiCal::PropertyValue::CalAddress.convert(self, val)}
241
+ end
242
+
243
+ # add one value to the ATTENDEE property
244
+ # one instances of CalAddress may be passed to this method
245
+ def add_attendee(ruby_value)
246
+ self.attendee_property << RiCal::PropertyValue::CalAddress.convert(self, ruby_value)
247
+ end
248
+
249
+ # remove one or more values from the ATTENDEE property
250
+ # one or more instances of CalAddress may be passed to this method
251
+ def remove_attendees(*ruby_values)
252
+ ruby_values.each {|val| self.attendee_property.delete(RiCal::PropertyValue::CalAddress.convert(self, val))}
253
+ end
254
+
255
+ # remove one value from the ATTENDEE property
256
+ # one instances of CalAddress may be passed to this method
257
+ def remove_attendee(ruby_value)
258
+ self.attendee_property.delete(RiCal::PropertyValue::CalAddress.convert(self, ruby_value))
259
+ end
260
+
261
+ # return the value of the ATTENDEE property
262
+ # which will be an array of instances of CalAddress
263
+ def attendee
264
+ attendee_property.map {|prop| prop ? prop.ruby_value : prop}
265
+ end
266
+
267
+ def attendee_property_from_string(line) # :nodoc:
268
+ attendee_property << RiCal::PropertyValue::CalAddress.new(self, line)
269
+ end
270
+
271
+ # return the the ATTACH property
272
+ # which will be an array of instances of RiCal::PropertyValueUri
273
+ #
274
+ # [purpose (from RFC 2445)]
275
+ # The property provides the capability to associate a document object with a calendar component.
276
+ #
277
+ # see RFC 2445 4.8.1.1 pp 77-78
278
+ def attach_property
279
+ @attach_property ||= []
280
+ end
281
+
282
+ # set the the ATTACH property
283
+ # one or more instances of RiCal::PropertyValueUri may be passed to this method
284
+ def attach_property=(*property_values)
285
+ @attach_property= property_values
286
+ end
287
+
288
+ # set the value of the ATTACH property to multiple values
289
+ # one or more instances of Uri may be passed to this method
290
+ def attachments=(ruby_values)
291
+ @attach_property = ruby_values.map {|val| RiCal::PropertyValue::Uri.convert(self, val)}
292
+ end
293
+
294
+ # set the value of the ATTACH property to a single value
295
+ # one instance of Uri may be passed to this method
296
+ def attach=(ruby_value)
297
+ @attach_property = [RiCal::PropertyValue::Uri.convert(self, ruby_value)]
298
+ end
299
+
300
+ # add one or more values to the ATTACH property
301
+ # one or more instances of Uri may be passed to this method
302
+ def add_attachments(*ruby_values)
303
+ ruby_values.each {|val| self.attach_property << RiCal::PropertyValue::Uri.convert(self, val)}
304
+ end
305
+
306
+ # add one value to the ATTACH property
307
+ # one instances of Uri may be passed to this method
308
+ def add_attach(ruby_value)
309
+ self.attach_property << RiCal::PropertyValue::Uri.convert(self, ruby_value)
310
+ end
311
+
312
+ # remove one or more values from the ATTACH property
313
+ # one or more instances of Uri may be passed to this method
314
+ def remove_attachments(*ruby_values)
315
+ ruby_values.each {|val| self.attach_property.delete(RiCal::PropertyValue::Uri.convert(self, val))}
316
+ end
317
+
318
+ # remove one value from the ATTACH property
319
+ # one instances of Uri may be passed to this method
320
+ def remove_attach(ruby_value)
321
+ self.attach_property.delete(RiCal::PropertyValue::Uri.convert(self, ruby_value))
322
+ end
323
+
324
+ # return the value of the ATTACH property
325
+ # which will be an array of instances of Uri
326
+ def attach
327
+ attach_property.map {|prop| prop ? prop.ruby_value : prop}
328
+ end
329
+
330
+ def attach_property_from_string(line) # :nodoc:
331
+ attach_property << RiCal::PropertyValue::Uri.new(self, line)
332
+ end
333
+
334
+ def export_properties_to(export_stream) #:nodoc:
335
+ export_prop_to(export_stream, "ACTION", @action_property)
336
+ export_prop_to(export_stream, "ATTENDEE", @attendee_property)
337
+ export_prop_to(export_stream, "DURATION", @duration_property)
338
+ export_prop_to(export_stream, "TRIGGER", @trigger_property)
339
+ export_prop_to(export_stream, "DESCRIPTION", @description_property)
340
+ export_prop_to(export_stream, "SUMMARY", @summary_property)
341
+ export_prop_to(export_stream, "REPEAT", @repeat_property)
342
+ export_prop_to(export_stream, "ATTACH", @attach_property)
343
+ end
344
+
345
+ def ==(o) #:nodoc:
346
+ if o.class == self.class
347
+ (action_property == o.action_property) &&
348
+ (attendee_property == o.attendee_property) &&
349
+ (duration_property == o.duration_property) &&
350
+ (trigger_property == o.trigger_property) &&
351
+ (description_property == o.description_property) &&
352
+ (summary_property == o.summary_property) &&
353
+ (repeat_property == o.repeat_property) &&
354
+ (attach_property == o.attach_property)
355
+ else
356
+ super
357
+ end
358
+ end
359
+
360
+ def initialize_copy(o) #:nodoc:
361
+ super
362
+ action_property = action_property && action_property.dup
363
+ attendee_property = attendee_property && attendee_property.dup
364
+ duration_property = duration_property && duration_property.dup
365
+ trigger_property = trigger_property && trigger_property.dup
366
+ description_property = description_property && description_property.dup
367
+ summary_property = summary_property && summary_property.dup
368
+ repeat_property = repeat_property && repeat_property.dup
369
+ attach_property = attach_property && attach_property.dup
370
+ end
371
+
372
+ def add_date_times_to(required_timezones) #:nodoc:
373
+ end
374
+
375
+ module ClassMethods #:nodoc:
376
+ def property_parser #:nodoc:
377
+ {"ACTION"=>:action_property_from_string, "ATTACH"=>:attach_property_from_string, "REPEAT"=>:repeat_property_from_string, "SUMMARY"=>:summary_property_from_string, "TRIGGER"=>:trigger_property_from_string, "ATTENDEE"=>:attendee_property_from_string, "DURATION"=>:duration_property_from_string, "DESCRIPTION"=>:description_property_from_string}
378
+ end
379
+ end
380
+
381
+ def self.included(mod) #:nodoc:
382
+ mod.extend ClassMethods
383
+ end
384
+
385
+ def mutual_exclusion_violation #:nodoc:
386
+ false
387
+ end
388
+ end
389
+ end
390
+ end