demingfactor-ri_cal 0.9.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 (167) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +402 -0
  3. data/Manifest.txt +161 -0
  4. data/README.txt +410 -0
  5. data/Rakefile +69 -0
  6. data/VERSION +1 -0
  7. data/bin/ri_cal +8 -0
  8. data/component_attributes/alarm.yml +10 -0
  9. data/component_attributes/calendar.yml +4 -0
  10. data/component_attributes/component_property_defs.yml +180 -0
  11. data/component_attributes/event.yml +45 -0
  12. data/component_attributes/freebusy.yml +16 -0
  13. data/component_attributes/journal.yml +35 -0
  14. data/component_attributes/timezone.yml +3 -0
  15. data/component_attributes/timezone_period.yml +11 -0
  16. data/component_attributes/todo.yml +46 -0
  17. data/copyrights.txt +1 -0
  18. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  19. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  20. data/docs/incrementers.txt +7 -0
  21. data/docs/rfc2445.pdf +0 -0
  22. data/lib/ri_cal/component/alarm.rb +19 -0
  23. data/lib/ri_cal/component/calendar.rb +257 -0
  24. data/lib/ri_cal/component/event.rb +58 -0
  25. data/lib/ri_cal/component/freebusy.rb +16 -0
  26. data/lib/ri_cal/component/journal.rb +27 -0
  27. data/lib/ri_cal/component/non_standard.rb +33 -0
  28. data/lib/ri_cal/component/t_z_info_timezone.rb +153 -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 +76 -0
  32. data/lib/ri_cal/component/timezone.rb +197 -0
  33. data/lib/ri_cal/component/todo.rb +42 -0
  34. data/lib/ri_cal/component.rb +256 -0
  35. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  36. data/lib/ri_cal/core_extensions/array.rb +7 -0
  37. data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
  38. data/lib/ri_cal/core_extensions/date.rb +13 -0
  39. data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
  40. data/lib/ri_cal/core_extensions/date_time.rb +15 -0
  41. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  42. data/lib/ri_cal/core_extensions/object.rb +8 -0
  43. data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
  44. data/lib/ri_cal/core_extensions/string.rb +8 -0
  45. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  46. data/lib/ri_cal/core_extensions/time/conversions.rb +42 -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 +55 -0
  49. data/lib/ri_cal/core_extensions/time.rb +14 -0
  50. data/lib/ri_cal/core_extensions.rb +11 -0
  51. data/lib/ri_cal/fast_date_time.rb +234 -0
  52. data/lib/ri_cal/floating_timezone.rb +32 -0
  53. data/lib/ri_cal/invalid_property_value.rb +8 -0
  54. data/lib/ri_cal/invalid_timezone_identifier.rb +20 -0
  55. data/lib/ri_cal/occurrence_enumerator.rb +265 -0
  56. data/lib/ri_cal/occurrence_period.rb +17 -0
  57. data/lib/ri_cal/parser.rb +148 -0
  58. data/lib/ri_cal/properties/alarm.rb +390 -0
  59. data/lib/ri_cal/properties/calendar.rb +164 -0
  60. data/lib/ri_cal/properties/event.rb +1523 -0
  61. data/lib/ri_cal/properties/freebusy.rb +593 -0
  62. data/lib/ri_cal/properties/journal.rb +1237 -0
  63. data/lib/ri_cal/properties/timezone.rb +150 -0
  64. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  65. data/lib/ri_cal/properties/todo.rb +1559 -0
  66. data/lib/ri_cal/properties.rb +12 -0
  67. data/lib/ri_cal/property_value/array.rb +27 -0
  68. data/lib/ri_cal/property_value/cal_address.rb +11 -0
  69. data/lib/ri_cal/property_value/date.rb +184 -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/date_time.rb +359 -0
  74. data/lib/ri_cal/property_value/duration.rb +110 -0
  75. data/lib/ri_cal/property_value/geo.rb +11 -0
  76. data/lib/ri_cal/property_value/integer.rb +12 -0
  77. data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
  78. data/lib/ri_cal/property_value/period.rb +86 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -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/occurrence_incrementer/by_day_incrementer.rb +86 -0
  85. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
  86. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
  87. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
  88. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
  89. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
  90. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
  91. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
  92. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
  93. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
  94. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
  95. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
  96. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
  97. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
  98. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
  99. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
  100. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
  101. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
  102. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
  103. data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -0
  104. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
  105. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +64 -0
  106. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
  107. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +53 -0
  108. data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
  109. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
  110. data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
  111. data/lib/ri_cal/property_value/text.rb +44 -0
  112. data/lib/ri_cal/property_value/uri.rb +11 -0
  113. data/lib/ri_cal/property_value/utc_offset.rb +33 -0
  114. data/lib/ri_cal/property_value/zulu_date_time.rb +34 -0
  115. data/lib/ri_cal/property_value.rb +159 -0
  116. data/lib/ri_cal/required_timezones.rb +55 -0
  117. data/lib/ri_cal.rb +187 -0
  118. data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
  119. data/performance/empty_propval/subject.rb +43 -0
  120. data/performance/paris_eastern/subject.rb +90 -0
  121. data/performance/penultimate_weekday/subject.rb +15 -0
  122. data/performance/psm_big_enum/ical.ics +3171 -0
  123. data/performance/psm_big_enum/subject.rb +16 -0
  124. data/performance/utah_cycling/subject.rb +55 -0
  125. data/ri_cal.gemspec +244 -0
  126. data/script/benchmark_subject +23 -0
  127. data/script/console +10 -0
  128. data/script/destroy +14 -0
  129. data/script/generate +14 -0
  130. data/script/profile_subject +29 -0
  131. data/script/txt2html +71 -0
  132. data/spec/ri_cal/bugreports_spec.rb +276 -0
  133. data/spec/ri_cal/component/alarm_spec.rb +12 -0
  134. data/spec/ri_cal/component/calendar_spec.rb +88 -0
  135. data/spec/ri_cal/component/event_spec.rb +735 -0
  136. data/spec/ri_cal/component/freebusy_spec.rb +12 -0
  137. data/spec/ri_cal/component/journal_spec.rb +37 -0
  138. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +60 -0
  139. data/spec/ri_cal/component/timezone_spec.rb +236 -0
  140. data/spec/ri_cal/component/todo_spec.rb +112 -0
  141. data/spec/ri_cal/component_spec.rb +224 -0
  142. data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
  143. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
  144. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
  145. data/spec/ri_cal/fast_date_time_spec.rb +77 -0
  146. data/spec/ri_cal/inf_loop_spec.rb +78 -0
  147. data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
  148. data/spec/ri_cal/parser_spec.rb +337 -0
  149. data/spec/ri_cal/property_value/date_spec.rb +53 -0
  150. data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
  151. data/spec/ri_cal/property_value/duration_spec.rb +126 -0
  152. data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
  153. data/spec/ri_cal/property_value/period_spec.rb +63 -0
  154. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
  155. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
  156. data/spec/ri_cal/property_value/text_spec.rb +25 -0
  157. data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
  158. data/spec/ri_cal/property_value_spec.rb +125 -0
  159. data/spec/ri_cal/required_timezones_spec.rb +67 -0
  160. data/spec/ri_cal_spec.rb +53 -0
  161. data/spec/spec.opts +4 -0
  162. data/spec/spec_helper.rb +50 -0
  163. data/tasks/gem_loader/load_active_support.rb +3 -0
  164. data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
  165. data/tasks/ri_cal.rake +412 -0
  166. data/tasks/spec.rake +102 -0
  167. metadata +246 -0
data/tasks/ri_cal.rake ADDED
@@ -0,0 +1,412 @@
1
+ #require 'active_support'
2
+ require 'yaml'
3
+ #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
4
+ #
5
+ # code stolen from ActiveSupport Gem
6
+ unless String.instance_methods.include?("camelize")
7
+ class String
8
+ def camelize
9
+ self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
10
+ end
11
+ end
12
+ end
13
+
14
+ class VEntityUpdater
15
+ Pluralization = {
16
+ "attach" => "attachments",
17
+ "categories" => "multiple_categories",
18
+ "free_busy" => "free_busies",
19
+ "security_class" => "security_classes",
20
+ "request_status" => "request_statuses",
21
+ "related_to" => "multiple_related_to",
22
+ "resources" => "multiple_resources"
23
+ }
24
+ def initialize(target, defs_file)
25
+ @target = target
26
+ @name=File.basename(target).sub(".rb","")
27
+ @indent = ""
28
+ @property_map = {}
29
+ @property_defs = YAML.load_file(defs_file)
30
+ @all_props = {}
31
+ @date_time_props = []
32
+ end
33
+
34
+ def property(prop_name_or_hash)
35
+ if Hash === prop_name_or_hash
36
+ name = prop_name_or_hash.keys[0]
37
+ override_options = prop_name_or_hash[name] || {}
38
+ else
39
+ name = prop_name_or_hash
40
+ override_options = {}
41
+ end
42
+ standard_options = @property_defs[name]
43
+ unless standard_options
44
+ puts "**** WARNING, no definition found for property #{name}"
45
+ standard_options = {}
46
+ end
47
+ options = {'type' => 'Text', 'ruby_name' => name}.merge(standard_options).merge(override_options)
48
+ named_property(name, options)
49
+ end
50
+
51
+ def indent(string)
52
+ @outfile.puts("#{@indent}#{string}")
53
+ end
54
+
55
+ def comment(*strings)
56
+ strings.each do |string|
57
+ indent("\# #{string}")
58
+ end
59
+ end
60
+
61
+ def no_doc(string)
62
+ indent("#{string} \# :nodoc:")
63
+ end
64
+
65
+ def blank_line
66
+ @outfile.puts
67
+ end
68
+
69
+ def describe_type(type)
70
+ case type
71
+ when 'date_time_or_date'
72
+ "either DateTime or Date"
73
+ when 'Text'
74
+ 'String'
75
+ else
76
+ type
77
+ end
78
+ end
79
+
80
+ def describe_property(type)
81
+ case type
82
+ when 'date_time_or_date'
83
+ "either RiCal::PropertyValue::DateTime or RiCal::PropertyValue::Date"
84
+ else
85
+ "RiCal::PropertyValue#{type}"
86
+ end
87
+ end
88
+
89
+ def type_class(type)
90
+ if type == 'date_time_or_date'
91
+ "RiCal::PropertyValue::DateTime"
92
+ else
93
+ "RiCal::PropertyValue::#{type}"
94
+ end
95
+ end
96
+
97
+ def cast_value(ruby_val, type)
98
+ "#{type_class(type)}.convert(self, #{ruby_val.inspect})"
99
+ end
100
+
101
+ def lazy_init_var(var, options)
102
+ const_val = options["constant_value"]
103
+ default_val = options["default_value"]
104
+ if options["multi"]
105
+ puts("*** Warning default_value of #{default_val} for multi-value property #{name} ignored") if default_val
106
+ puts("*** Warning const_value of #{const_val} for multi-value property #{name} ignored") if const_val
107
+ if var
108
+ "@#{var} ||= []"
109
+ else
110
+ "[]"
111
+ end
112
+ else
113
+ puts("*** Warning default_value of #{default_val} for property #{name} with constant_value of #{const_val}") if const_val && default_val
114
+ init_val = const_val || default_val
115
+ if init_val
116
+ if var
117
+ "@#{var} ||= #{cast_value(init_val, options["type"])}"
118
+ else
119
+ init_val.inspect
120
+ end
121
+ else
122
+ "@#{var}"
123
+ end
124
+ end
125
+ end
126
+
127
+ def pluralize(name)
128
+ Pluralization[name] || "#{name}s"
129
+ end
130
+
131
+ def named_property(name, options)
132
+ ruby_name = options['ruby_name']
133
+ multi = options['multi']
134
+ type = options['type']
135
+ rfc_ref = options['rfc_ref']
136
+ conflicts = options['conflicts_with']
137
+ type_constraint = options['type_constraint']
138
+ options.keys.each do |opt_key|
139
+ unless %w{
140
+ ruby_name
141
+ type
142
+ multi
143
+ rfc_ref
144
+ conflicts_with
145
+ purpose
146
+ constant_value
147
+ default_value
148
+ }.include?(opt_key)
149
+ puts "**** WARNING: unprocessed option key #{opt_key} for property #{name}"
150
+ end
151
+ end
152
+ if conflicts
153
+ mutually_exclusive(name, *conflicts)
154
+ end
155
+ needs_tz_access = %w{OccurrenceList date_time_or_date DateTime Date}.include?(type)
156
+ ruby_name = ruby_name.tr("-", "_")
157
+ ruby_method = ruby_name.downcase
158
+ property = "#{name.tr("-", "_").downcase}_property"
159
+ if type_constraint != 'must_be_utc' && %w[date_time_or_date DateTime Period OccurrenceList].include?(type)
160
+ @date_time_props << property
161
+ end
162
+ @all_props[property] = name.upcase
163
+ @property_map[name.upcase] = :"#{property}_from_string"
164
+ parent_set = needs_tz_access ? " ? property_value.for_parent(self) : nil" : ""
165
+ if type == 'date_time_or_date'
166
+ line_evaluator = "RiCal::PropertyValue::DateTime.or_date(self, line)"
167
+ else
168
+ line_evaluator = "#{type_class(type)}.new(self, line)"
169
+ end
170
+
171
+ if %w{Array, OccurrenceList}.include?(type)
172
+ ruby_val_parm = "*ruby_value"
173
+ val_parm = "*val"
174
+ else
175
+ ruby_val_parm = "ruby_value"
176
+ val_parm = "val"
177
+ end
178
+ blank_line
179
+ if multi
180
+ comment(
181
+ "return the the #{name.upcase} property",
182
+ "which will be an array of instances of #{describe_property(type)}"
183
+ )
184
+ comment("", "[purpose (from RFC 2445)]", options["purpose"]) if options["purpose"]
185
+ comment("", "see RFC 2445 #{rfc_ref}") if rfc_ref
186
+ indent("def #{property}")
187
+ indent(" #{lazy_init_var(property,options)}")
188
+ indent("end")
189
+ unless (options["constant_value"])
190
+ plural_ruby_method = pluralize(ruby_method)
191
+ blank_line
192
+ comment("set the the #{name.upcase} property")
193
+ comment("one or more instances of #{describe_property(type)} may be passed to this method")
194
+ indent("def #{property}=(*property_values)")
195
+ if needs_tz_access
196
+ indent(" @#{property}= property_values.map{|prop| prop.for_parent(self)}")
197
+ else
198
+ indent(" @#{property}= property_values")
199
+ end
200
+ indent("end")
201
+ blank_line
202
+ comment("set the value of the #{name.upcase} property to multiple values")
203
+ comment("one or more instances of #{describe_type(type)} may be passed to this method")
204
+ indent("def #{plural_ruby_method}=(ruby_values)")
205
+ indent(" @#{property} = ruby_values.map {|val| #{type_class(type)}.convert(self, #{val_parm})}")
206
+ indent("end")
207
+ blank_line
208
+ comment("set the value of the #{name.upcase} property to a single value")
209
+ comment("one instance of #{describe_type(type)} may be passed to this method")
210
+ indent("def #{ruby_method}=(#{ruby_val_parm})")
211
+ indent(" @#{property} = [#{type_class(type)}.convert(self, #{ruby_val_parm})]")
212
+ indent("end")
213
+ blank_line
214
+ comment("add one or more values to the #{name.upcase} property")
215
+ comment("one or more instances of #{describe_type(type)} may be passed to this method")
216
+ indent("def add_#{plural_ruby_method}(*ruby_values)")
217
+ indent(" ruby_values.each {|val| self.#{property} << #{type_class(type)}.convert(self, #{val_parm})}")
218
+ indent("end")
219
+ blank_line
220
+ comment("add one value to the #{name.upcase} property")
221
+ comment("one instances of #{describe_type(type)} may be passed to this method")
222
+ indent("def add_#{ruby_method}(#{ruby_val_parm})")
223
+ indent(" self.#{property} << #{type_class(type)}.convert(self, #{ruby_val_parm})")
224
+ indent("end")
225
+ blank_line
226
+ comment("remove one or more values from the #{name.upcase} property")
227
+ comment("one or more instances of #{describe_type(type)} may be passed to this method")
228
+ indent("def remove_#{plural_ruby_method}(*ruby_values)")
229
+ indent(" ruby_values.each {|val| self.#{property}.delete(#{type_class(type)}.convert(self, #{val_parm}))}")
230
+ indent("end")
231
+ blank_line
232
+ comment("remove one value from the #{name.upcase} property")
233
+ comment("one instances of #{describe_type(type)} may be passed to this method")
234
+ indent("def remove_#{ruby_method}(#{ruby_val_parm})")
235
+ indent(" self.#{property}.delete(#{type_class(type)}.convert(self, #{ruby_val_parm}))")
236
+ indent("end")
237
+ end
238
+ blank_line
239
+ comment("return the value of the #{name.upcase} property")
240
+ comment("which will be an array of instances of #{describe_type(type)}")
241
+ indent("def #{ruby_method}")
242
+ indent(" #{property}.map {|prop| prop ? prop.ruby_value : prop}")
243
+ indent("end")
244
+ blank_line
245
+ no_doc("def #{property}_from_string(line)")
246
+ indent(" #{property} << #{line_evaluator}")
247
+ indent("end")
248
+ else
249
+ comment(
250
+ "return the the #{name.upcase} property",
251
+ "which will be an instances of #{describe_property(type)}"
252
+ )
253
+ comment("", "[purpose (from RFC 2445)]", options["purpose"]) if options["purpose"]
254
+ comment("", "see RFC 2445 #{rfc_ref}") if rfc_ref
255
+ indent("def #{property}")
256
+ indent(" #{lazy_init_var(property,options)}")
257
+ indent("end")
258
+ unless (options["constant_value"])
259
+ blank_line
260
+ comment("set the #{name.upcase} property")
261
+ comment("property value should be an instance of #{describe_property(type)}")
262
+ indent("def #{property}=(property_value)")
263
+ indent(" @#{property} = property_value#{parent_set}")
264
+ if conflicts
265
+ conflicts.each do |conflict|
266
+ indent(" @#{conflict}_property = nil")
267
+ end
268
+ end
269
+ indent("end")
270
+ blank_line
271
+ comment("set the value of the #{name.upcase} property")
272
+ indent("def #{ruby_method}=(ruby_value)")
273
+ indent(" self.#{property}= #{type_class(type)}.convert(self, ruby_value)")
274
+ indent("end")
275
+ end
276
+ blank_line
277
+ comment("return the value of the #{name.upcase} property")
278
+ comment("which will be an instance of #{describe_type(type)}")
279
+ indent("def #{ruby_method}")
280
+ indent(" #{property} ? #{property}.ruby_value : nil")
281
+ indent("end")
282
+ blank_line
283
+ no_doc("def #{property}_from_string(line)")
284
+ indent(" @#{property} = #{line_evaluator}")
285
+ indent("end")
286
+ @outfile.puts
287
+ end
288
+ end
289
+
290
+ def mutually_exclusive *prop_names
291
+ exclusives = prop_names.map {|str| :"#{str}_property"}.sort {|a, b| a.to_s <=> b.to_s}
292
+ unless mutually_exclusive_properties.include?(exclusives)
293
+ mutually_exclusive_properties << prop_names.map {|str| :"#{str}_property"}
294
+ end
295
+ end
296
+
297
+ def mutually_exclusive_properties
298
+ @mutually_exclusive_properties ||= []
299
+ end
300
+
301
+ def generate_support_methods
302
+ blank_line
303
+ indent("def export_properties_to(export_stream) #:nodoc:")
304
+ @all_props.each do |prop_attr, prop_name|
305
+ indent(" export_prop_to(export_stream, #{prop_name.inspect}, @#{prop_attr})")
306
+ end
307
+ indent("end")
308
+ blank_line
309
+ indent("def ==(o) #:nodoc:")
310
+ indent(" if o.class == self.class")
311
+ @all_props.keys.each_with_index do |prop_name, i|
312
+ and_str = i < @all_props.length - 1 ? " &&" : ""
313
+ indent(" (#{prop_name} == o.#{prop_name})#{and_str}")
314
+ end
315
+ indent(" else")
316
+ indent(" super")
317
+ indent(" end")
318
+ indent("end")
319
+ blank_line
320
+ indent("def initialize_copy(o) #:nodoc:")
321
+ indent(" super")
322
+ @all_props.each_key do |prop_name|
323
+ indent(" #{prop_name} = #{prop_name} && #{prop_name}.dup")
324
+ end
325
+ indent("end")
326
+ blank_line
327
+ indent("def add_date_times_to(required_timezones) #:nodoc:")
328
+ @date_time_props.each do | prop_name|
329
+ indent(" add_property_date_times_to(required_timezones, #{prop_name})")
330
+ end
331
+ indent("end")
332
+ blank_line
333
+ indent("module ClassMethods #:nodoc:")
334
+ indent(" def property_parser #:nodoc:")
335
+ indent(" #{@property_map.inspect}")
336
+ indent(" end")
337
+ indent("end")
338
+ blank_line
339
+ indent("def self.included(mod) #:nodoc:")
340
+ indent(" mod.extend ClassMethods")
341
+ indent("end")
342
+ blank_line
343
+ indent("def mutual_exclusion_violation #:nodoc:")
344
+ if mutually_exclusive_properties.empty?
345
+ indent(" false")
346
+ else
347
+ mutually_exclusive_properties.each do |mutex_set|
348
+ indent(" return true if #{mutex_set.inspect}.inject(0) {|sum, prop| send(prop) ? sum + 1 : sum} > 1")
349
+ end
350
+ indent(" false")
351
+ end
352
+ indent "end"
353
+ end
354
+
355
+ def update
356
+ File.open(File.join(File.dirname(__FILE__), '..', 'lib', 'ri_cal', 'properties' , "#{@name}.rb"), 'w') do |ruby_out_file|
357
+ @outfile = ruby_out_file
358
+ module_name = @name.camelize
359
+ class_name = module_name.sub(/Properties$/, "")
360
+ ruby_out_file.puts("module RiCal")
361
+ ruby_out_file.puts(" module Properties #:nodoc:")
362
+ @indent = " "
363
+ ruby_out_file.puts(" #- ©2009 Rick DeNatale")
364
+ ruby_out_file.puts(" #- All rights reserved. Refer to the file README.txt for the license")
365
+ ruby_out_file.puts(" #")
366
+ ruby_out_file.puts(" # Properties::#{module_name} provides property accessing methods for the #{class_name} class")
367
+ ruby_out_file.puts(" # This source file is generated by the rical:gen_propmodules rake tasks, DO NOT EDIT")
368
+ ruby_out_file.puts(" module #{module_name}")
369
+ @indent = " "
370
+ YAML.load_file(File.join(File.dirname(__FILE__), '..', 'component_attributes', "#{@name}.yml")).each do |att_def|
371
+ property(att_def)
372
+ end
373
+ generate_support_methods
374
+ ruby_out_file.puts(" end")
375
+ ruby_out_file.puts(" end")
376
+ ruby_out_file.puts("end")
377
+ end
378
+ @outfile = nil
379
+ end
380
+ end
381
+
382
+ def updateTask srcGlob, taskSymbol
383
+ targetDir = File.join(File.dirname(__FILE__), '..', 'lib', 'ri_cal', 'properties')
384
+ defsFile = File.join(File.dirname(__FILE__), '..', 'component_attributes', 'component_property_defs.yml')
385
+ FileList[srcGlob].each do |f|
386
+ unless f == defsFile
387
+ target = File.join targetDir, File.basename(f).gsub(".yml", ".rb")
388
+ file target => [f, defsFile, __FILE__] do |t|
389
+ VEntityUpdater.new(target, defsFile).update
390
+ end
391
+ task taskSymbol => target
392
+ end
393
+ end
394
+ end
395
+
396
+
397
+ namespace :rical do
398
+
399
+ desc '(RE)Generate VEntity attributes'
400
+ task :gen_propmodules do |t|
401
+ end
402
+
403
+ updateTask File.join(File.dirname(__FILE__), '..', '/component_attributes', '*.yml'), :gen_propmodules
404
+
405
+ end # namespace :rical
406
+
407
+ desc 'add or update copyright in code and specs'
408
+ task :copyrights do
409
+ require 'mmcopyrights'
410
+ MM::Copyrights.process('lib', "rb", "#-", IO.read('copyrights.txt'))
411
+ MM::Copyrights.process('spec', "rb", "#-", IO.read('copyrights.txt'))
412
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,102 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run all specs"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ t.ruby_opts << "-rubygems"
22
+ end
23
+
24
+ namespace :spec do
25
+ desc "Run all specs in the presence of ActiveSupport"
26
+ Spec::Rake::SpecTask.new(:with_active_support) do |t|
27
+ t.spec_opts = ['--options', "spec/spec.opts"]
28
+ t.spec_files = FileList['spec/**/*_spec.rb']
29
+ t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_active_support])}"
30
+ end
31
+
32
+ desc "Run all specs in the presence of the tzinfo gem"
33
+ Spec::Rake::SpecTask.new(:with_tzinfo_gem) do |t|
34
+ t.spec_opts = ['--options', "spec/spec.opts"]
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_tzinfo_gem])}"
37
+ end
38
+ multiruby_path = `which multiruby`.chomp
39
+ if multiruby_path.length > 0 && Spec::Rake::SpecTask.instance_methods.include?("ruby_cmd")
40
+ namespace :multi do
41
+ desc "Run all specs with multiruby and ActiveSupport"
42
+ Spec::Rake::SpecTask.new(:with_active_support) do |t|
43
+ t.spec_opts = ['--options', "spec/spec.opts"]
44
+ t.spec_files = FileList['spec/**/*_spec.rb']
45
+ t.ruby_cmd = "#{multiruby_path}"
46
+ t.verbose = true
47
+ t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_active_support])}"
48
+ end
49
+
50
+ desc "Run all specs multiruby and the tzinfo gem"
51
+ Spec::Rake::SpecTask.new(:with_tzinfo_gem) do |t|
52
+ t.spec_opts = ['--options', "spec/spec.opts"]
53
+ t.spec_files = FileList['spec/**/*_spec.rb']
54
+ t.ruby_cmd = "#{multiruby_path}"
55
+ t.verbose = true
56
+ t.ruby_opts << "-r #{File.join(File.dirname(__FILE__), *%w[gem_loader load_tzinfo_gem])}"
57
+ end
58
+ end
59
+
60
+ desc "run all specs under multiruby with ActiveSupport and also with the tzinfo gem"
61
+ task :multi => [:"spec:multi:with_active_support", :"spec:multi:with_tzinfo_gem"]
62
+ end
63
+ end
64
+
65
+ if RUBY_VERSION.match(/^1\.8\./)
66
+ desc 'Run all specs with RCov'
67
+ Spec::Rake::SpecTask.new(:rcov) do |t|
68
+ t.spec_opts = ['--options', "spec/spec.opts"]
69
+ t.spec_files = FileList['spec/**/*_spec.rb']
70
+ t.rcov = true
71
+ t.rcov_dir = "coverage"
72
+ t.rcov_opts = ['--exclude', 'spec']
73
+ end
74
+ end
75
+
76
+ namespace :performance do
77
+ desc 'Run all benchmarks'
78
+ task :benchmark do
79
+ bench_script = File.join(File.dirname(__FILE__), '..', '/script', 'benchmark_subject')
80
+ bench_file = File.join(File.dirname(__FILE__), '..', '/performance_data', 'benchmarks.out')
81
+ cat = ">"
82
+ FileList[File.join(File.dirname(__FILE__), '..', '/performance', '*')].each do |f|
83
+ cmd = "#{bench_script} #{File.basename(f)} #{cat} #{bench_file}"
84
+ puts cmd
85
+ `#{cmd}`
86
+ cat = '>>'
87
+ end
88
+ end
89
+
90
+ desc 'Run all profiles'
91
+ task :profile do
92
+ bench_script = File.join(File.dirname(__FILE__), '..', '/script', 'profile_subject')
93
+ FileList[File.join(File.dirname(__FILE__), '..', '/performance', '*')].each do |f|
94
+ cmd = "#{bench_script} #{File.basename(f)}"
95
+ puts cmd
96
+ `#{cmd}`
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+