vobject 0.1.0 → 1.0.2

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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/macos.yml +38 -0
  3. data/.github/workflows/ubuntu.yml +56 -0
  4. data/.github/workflows/windows.yml +40 -0
  5. data/.hound.yml +3 -0
  6. data/.rubocop.tb.yml +650 -0
  7. data/.rubocop.yml +1077 -0
  8. data/Gemfile +1 -1
  9. data/LICENSE.txt +21 -17
  10. data/README.adoc +151 -0
  11. data/Rakefile +1 -1
  12. data/lib/c.rb +173 -0
  13. data/lib/error.rb +19 -0
  14. data/lib/vcalendar.rb +77 -0
  15. data/lib/vcard.rb +67 -0
  16. data/lib/vobject.rb +13 -170
  17. data/lib/vobject/component.rb +87 -36
  18. data/lib/vobject/parameter.rb +116 -0
  19. data/lib/vobject/parametervalue.rb +26 -0
  20. data/lib/vobject/property.rb +134 -55
  21. data/lib/vobject/propertyvalue.rb +46 -0
  22. data/lib/vobject/vcalendar/component.rb +106 -0
  23. data/lib/vobject/vcalendar/grammar.rb +595 -0
  24. data/lib/vobject/vcalendar/paramcheck.rb +259 -0
  25. data/lib/vobject/vcalendar/propertyparent.rb +98 -0
  26. data/lib/vobject/vcalendar/propertyvalue.rb +606 -0
  27. data/lib/vobject/vcalendar/typegrammars.rb +605 -0
  28. data/lib/vobject/vcard/v3_0/component.rb +40 -0
  29. data/lib/vobject/vcard/v3_0/grammar.rb +175 -0
  30. data/lib/vobject/vcard/v3_0/paramcheck.rb +110 -0
  31. data/lib/vobject/vcard/v3_0/parameter.rb +17 -0
  32. data/lib/vobject/vcard/v3_0/property.rb +18 -0
  33. data/lib/vobject/vcard/v3_0/propertyvalue.rb +401 -0
  34. data/lib/vobject/vcard/v3_0/typegrammars.rb +425 -0
  35. data/lib/vobject/vcard/v4_0/component.rb +40 -0
  36. data/lib/vobject/vcard/v4_0/grammar.rb +224 -0
  37. data/lib/vobject/vcard/v4_0/paramcheck.rb +269 -0
  38. data/lib/vobject/vcard/v4_0/parameter.rb +18 -0
  39. data/lib/vobject/vcard/v4_0/property.rb +63 -0
  40. data/lib/vobject/vcard/v4_0/propertyvalue.rb +404 -0
  41. data/lib/vobject/vcard/v4_0/typegrammars.rb +539 -0
  42. data/lib/vobject/version.rb +1 -1
  43. data/vobject.gemspec +19 -16
  44. metadata +81 -26
  45. data/.travis.yml +0 -5
  46. data/README.md +0 -94
@@ -0,0 +1,259 @@
1
+ require "rsec"
2
+ require "set"
3
+ require "uri"
4
+ require "date"
5
+ require "tzinfo"
6
+ include Rsec::Helpers
7
+ require_relative "../../c"
8
+ require_relative "../../error"
9
+
10
+ module Vobject::Vcalendar
11
+ class Paramcheck
12
+ class << self
13
+ def paramcheck(strict, prop, params, ctx)
14
+ errors = []
15
+ if params && params[:ALTREP]
16
+ case prop
17
+ when :COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES, :SUMMARY,
18
+ :CONTACT, :NAME, :IMAGE
19
+ else
20
+ parse_err(strict, errors, "(:ALTREP parameter given for #{prop}", ctx)
21
+ end
22
+ end
23
+ if params && params[:CN]
24
+ case prop
25
+ when :ATTENDEE, :ORGANIZER
26
+ else
27
+ parse_err(strict, errors, "(:CN parameter given for #{prop}", ctx)
28
+ end
29
+ end
30
+ if params && params[:CUTYPE]
31
+ case prop
32
+ when :ATTENDEE
33
+ else
34
+ parse_err(strict, errors, "(:CUTYPE parameter given for #{prop}", ctx)
35
+ end
36
+ end
37
+ if params && params[:DELEGATED_FROM]
38
+ case prop
39
+ when :ATTENDEE
40
+ else
41
+ parse_err(strict, errors, "(:DELEGATED_FROM parameter given for #{prop}", ctx)
42
+ end
43
+ end
44
+ if params && params[:DELEGATED_TO]
45
+ case prop
46
+ when :ATTENDEE
47
+ else
48
+ parse_err(strict, errors, "(:DELEGATED_TO parameter given for #{prop}", ctx)
49
+ end
50
+ end
51
+ if params && params[:DIR]
52
+ case prop
53
+ when :ATTENDEE, :ORGANIZER
54
+ else
55
+ parse_err(strict, errors, "(:DIR parameter given for #{prop}", ctx)
56
+ end
57
+ end
58
+ if params && params[:ENCODING]
59
+ case prop
60
+ when :ATTACH, :IMAGE
61
+ else
62
+ parse_err(strict, errors, "(:ENCODING parameter given for #{prop}", ctx)
63
+ end
64
+ end
65
+ if params && params[:FMTTYPE]
66
+ case prop
67
+ when :ATTACH, :IMAGE
68
+ else
69
+ parse_err(strict, errors, "(:FMTTYPE parameter given for #{prop}", ctx)
70
+ end
71
+ end
72
+ if params && params[:FBTYPE]
73
+ case prop
74
+ when :FREEBUSY
75
+ else
76
+ parse_err(strict, errors, "(:FBTYPE parameter given for #{prop}", ctx)
77
+ end
78
+ end
79
+ if params && params[:LANGUAGE]
80
+ case prop
81
+ when :CATEGORIES, :COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES,
82
+ :SUMMARY, :TZNAME, :ATTENDEE, :CONTACT, :ORGANIZER, :REQUEST_STATUS,
83
+ :NAME, :CONFERENCE
84
+ else
85
+ parse_err(strict, errors, "(:LANGUAGE parameter given for #{prop}", ctx)
86
+ end
87
+ end
88
+ if params && params[:MEMBER]
89
+ case prop
90
+ when :ATTENDEE
91
+ else
92
+ parse_err(strict, errors, "(:MEMBER parameter given for #{prop}", ctx)
93
+ end
94
+ end
95
+ if params && params[:PARTSTAT]
96
+ case prop
97
+ when :ATTENDEE
98
+ else
99
+ parse_err(strict, errors, "(:PARTSTAT parameter given for #{prop}", ctx)
100
+ end
101
+ end
102
+ if params && params[:RANGE]
103
+ case prop
104
+ when :RECURRENCE_ID
105
+ else
106
+ parse_err(strict, errors, "(:RANGE parameter given for #{prop}", ctx)
107
+ end
108
+ end
109
+ if params && params[:RELATED]
110
+ case prop
111
+ when :TRIGGER
112
+ else
113
+ parse_err(strict, errors, "(:RELATED parameter given for #{prop}", ctx)
114
+ end
115
+ end
116
+ if params && params[:RELTYPE]
117
+ case prop
118
+ when :RELATED_TO
119
+ else
120
+ parse_err(strict, errors, "(:RELTYPE parameter given for #{prop}", ctx)
121
+ end
122
+ end
123
+ if params && params[:ROLE]
124
+ case prop
125
+ when :ATTENDEE
126
+ else
127
+ parse_err(strict, errors, "(:ROLE parameter given for #{prop}", ctx)
128
+ end
129
+ end
130
+ if params && params[:RSVP]
131
+ case prop
132
+ when :ATTENDEE
133
+ else
134
+ parse_err(strict, errors, "(:RSVP parameter given for #{prop}", ctx)
135
+ end
136
+ end
137
+ if params && params[:SENT_BY]
138
+ case prop
139
+ when :ATTENDEE, :ORGANIZER
140
+ else
141
+ parse_err(strict, errors, "(:SENT_BY parameter given for #{prop}", ctx)
142
+ end
143
+ end
144
+ if params && params[:TZID]
145
+ case prop
146
+ when :DTEND, :DUE, :DTSTART, :RECURRENCE_ID, :EXDATE, :RDATE
147
+ else
148
+ parse_err(strict, errors, "(:TZID parameter given for #{prop}", ctx)
149
+ end
150
+ end
151
+ if params && params[:DISPLAY]
152
+ case prop
153
+ when :IMAGE
154
+ else
155
+ parse_err(strict, errors, "(:DISPLAY parameter given for #{prop}", ctx)
156
+ end
157
+ end
158
+ if params && params[:FEATURE]
159
+ case prop
160
+ when :CONFERENCE
161
+ else
162
+ parse_err(strict, errors, "(:FEATURE parameter given for #{prop}", ctx)
163
+ end
164
+ end
165
+ if params && params[:LABEL]
166
+ case prop
167
+ when :CONFERENCE
168
+ else
169
+ parse_err(strict, errors, "(:LABEL parameter given for #{prop}", ctx)
170
+ end
171
+ end
172
+ if params && params[:EMAIL]
173
+ case prop
174
+ when :ORGANIZER, :ATTENDEE
175
+ else
176
+ parse_err(strict, errors, "(:EMAIL parameter given for #{prop}", ctx)
177
+ end
178
+ end
179
+
180
+ case prop
181
+ when :TZURL, :URL, :CONFERENCE, :SOURCE
182
+ params.each do |key, val|
183
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("uri") != 0
184
+ end
185
+ when :FREEBUSY
186
+ params.each do |key, val|
187
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("period") != 0
188
+ end
189
+ when :COMPLETED
190
+ params.each do |key, val|
191
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0
192
+ end
193
+ when :PERCENT_COMPLETE, :PRIORITY, :REPEAT, :SEQUENCE
194
+ params.each do |key, val|
195
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("integer") != 0
196
+ end
197
+ when :DURATION, :REFRESH_INTERVAL
198
+ params.each do |key, val|
199
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("duration") != 0
200
+ end
201
+ when :GEO
202
+ params.each do |key, val|
203
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("float") != 0
204
+ end
205
+ when :CREATED, :DTSTAMP, :LAST_MODIFIED
206
+ params.each do |key, val|
207
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0
208
+ end
209
+ when :CALSCALE, :METHOD, :PRODID, :VERSION, :CATEGORIES, :CLASS,
210
+ :COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES, :STATUS, :SUMMARY,
211
+ :TRANSP, :TZID, :TZNAME, :CONTACT, :RELATED_TO, :UID, :ACTION,
212
+ :REQUEST_STATUS, :COLOR, :NAME
213
+ params.each do |key, val|
214
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("text") != 0
215
+ end
216
+ when :DTEND, :DUE, :DTSTART, :RECURRENCE_ID, :EXDATE
217
+ params.each do |key, val|
218
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0 && val.casecmp("date") != 0
219
+ end
220
+ when :RDATE
221
+ params.each do |key, val|
222
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("period") != 0 && val.casecmp("date") != 0 && val.casecmp("date-time") != 0
223
+ end
224
+ when :RRULE
225
+ params.each do |key, val|
226
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("recur") != 0
227
+ end
228
+ when :TZOFFSETFROM, :TZOFFSETTO
229
+ params.each do |key, val|
230
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("utc-offset") != 0
231
+ end
232
+ when :ATTENDEE, :ORGANIZER
233
+ params.each do |key, val|
234
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("cal-address") != 0
235
+ end
236
+ when :TRIGGER
237
+ params.each do |key, val|
238
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("duration") != 0 && val.casecmp("date-time") != 0
239
+ end
240
+ when :ATTACH, :IMAGE
241
+ params.each do |key, val|
242
+ parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("uri") != 0 && val.casecmp("binary") != 0
243
+ end
244
+ end
245
+ errors
246
+ end
247
+
248
+ private
249
+
250
+ def parse_err(strict, errors, msg, ctx)
251
+ if strict
252
+ raise ctx.report_error msg, "source"
253
+ else
254
+ errors << ctx.report_error(msg, "source")
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,98 @@
1
+ require "rsec"
2
+ require "set"
3
+ require "uri"
4
+ require "date"
5
+ require "tzinfo"
6
+ include Rsec::Helpers
7
+ require_relative "../../c"
8
+ require_relative "../../error"
9
+ require "vobject"
10
+
11
+ module Vobject::Vcalendar
12
+ class Typegrammars
13
+ class << self
14
+ # Ensure each property belongs to a legal component
15
+ def property_parent(strict, key, component, _value, ctx1)
16
+ errors = []
17
+ if key !~ /^x/i && registered_propname?(key.to_s)
18
+ case component
19
+ when :EVENT
20
+ case key
21
+ when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
22
+ :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE, :STATUS,
23
+ :SUMMARY, :TRANSP, :URL, :RECURRENCE_ID, :RRULE, :DTEND, :DURATION,
24
+ :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
25
+ :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
26
+ else
27
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
28
+ end
29
+ when :TODO
30
+ case key
31
+ when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
32
+ :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :PERCENT_COMPLETED, :SEQUENCE, :STATUS,
33
+ :SUMMARY, :URL, :RECURRENCE_ID, :RRULE, :DUE, :DURATION,
34
+ :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
35
+ :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
36
+ else
37
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
38
+ end
39
+ when :JOURNAL
40
+ case key
41
+ when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
42
+ :LAST_MOD, :ORGANIZER, :RECURRENCE_ID, :SEQUENCE, :STATUS,
43
+ :SUMMARY, :URL, :RRULE,
44
+ :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
45
+ :RSTATUS, :RELATED, :RDATE, :COLOR, :IMAGE
46
+ else
47
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
48
+ end
49
+ when :FREEBUSY
50
+ case key
51
+ when :DTSTAMP, :UID, :CONTACT, :DTSTART, :DTEND, :ORGANIZER, :URL,
52
+ :ATTENDEE, :COMMENT, :FREEBUSY, :RSTATUS
53
+ else
54
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
55
+ end
56
+ when :TIMEZONE
57
+ case key
58
+ when :TZID, :LAST_MODIFIED, :TZURL
59
+ else
60
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
61
+ end
62
+ when :DAYLIGHT, :STANDARD
63
+ case key
64
+ when :DTSTART, :TZOFFSETTO, :TZOFFSETFROM, :RRULE,
65
+ :COMMENT, :RDATE, :TZNAME
66
+ else
67
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
68
+ end
69
+ when :ALARM
70
+ case key
71
+ when :ACTION, :TRIGGER, :DURATION, :REPEAT, :ATTACH, :DESCRIPTION,
72
+ :SUMMARY, :ATTENDEE
73
+ else
74
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
75
+ end
76
+ when :VAVAILABILITY
77
+ case key
78
+ when :DTSTAMP, :UID, :BUSYTYPE, :CLASS, :CREATED, :DESCRIPTION,
79
+ :DTSTART, :LAST_MODIFIED, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE,
80
+ :SUMMARY, :URL, :DTEND, :DURATION, :CATEGORIES, :COMMENT, :CONTACT
81
+ else
82
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
83
+ end
84
+ when :AVAILABLE
85
+ case key
86
+ when :DTSTAMP, :DTSTART, :UID, :DTEND, :DURATION, :CREATED,
87
+ :DESCRIPTION, :LAST_MODIFIED, :LOCATION, :RECURRENCE_ID, :RRULE,
88
+ :SUMMARY, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE, :RDATE
89
+ else
90
+ parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
91
+ end
92
+ end
93
+ end
94
+ errors
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,606 @@
1
+ require "vobject"
2
+ require "vobject/propertyvalue"
3
+
4
+ module Vobject
5
+ module Vcalendar
6
+ module PropertyValue
7
+ class Text < Vobject::PropertyValue
8
+ class << self
9
+ def escape(x)
10
+ # temporarily escape \\ as \u007f, which is banned from text
11
+ x.tr("\\", "\u007f").gsub(/\n/, "\\n").gsub(/,/, "\\,").
12
+ gsub(/;/, "\\;").gsub(/\u007f/, "\\\\\\\\")
13
+ end
14
+ end
15
+
16
+ def initialize(val)
17
+ self.value = val
18
+ self.type = "text"
19
+ end
20
+
21
+ def to_s
22
+ Text.escape value
23
+ end
24
+
25
+ def to_hash
26
+ value
27
+ end
28
+ end
29
+
30
+ class ClassValue < Text
31
+ def initialize(val)
32
+ self.value = val
33
+ self.type = "classvalue"
34
+ end
35
+
36
+ def to_hash
37
+ value
38
+ end
39
+ end
40
+
41
+ class TranspValue < Text
42
+ def initialize(val)
43
+ self.value = val
44
+ self.type = "transpvalue"
45
+ end
46
+
47
+ def to_hash
48
+ value
49
+ end
50
+ end
51
+
52
+ class ActionValue < Text
53
+ def initialize(val)
54
+ self.value = val
55
+ self.type = "actionvalue"
56
+ end
57
+
58
+ def to_hash
59
+ value
60
+ end
61
+ end
62
+
63
+ class MethodValue < Text
64
+ def initialize(val)
65
+ self.value = val
66
+ self.type = "methodvalue"
67
+ end
68
+
69
+ def to_hash
70
+ value
71
+ end
72
+ end
73
+
74
+ class Busytype < Text
75
+ def initialize(val)
76
+ self.value = val
77
+ self.type = "busytype"
78
+ end
79
+
80
+ def to_hash
81
+ value
82
+ end
83
+ end
84
+
85
+ class Color < Text
86
+ def initialize(val)
87
+ self.value = val
88
+ self.type = "color"
89
+ end
90
+
91
+ def to_hash
92
+ value
93
+ end
94
+ end
95
+
96
+ class EventStatus < Text
97
+ def initialize(val)
98
+ self.value = val
99
+ self.type = "eventstatus"
100
+ end
101
+
102
+ def to_hash
103
+ value
104
+ end
105
+ end
106
+
107
+ class Todostatus < Text
108
+ def initialize(val)
109
+ self.value = val
110
+ self.type = "todostatus"
111
+ end
112
+
113
+ def to_hash
114
+ value
115
+ end
116
+ end
117
+
118
+ class Journalstatus < Text
119
+ def initialize(val)
120
+ self.value = val
121
+ self.type = "journalstatus"
122
+ end
123
+
124
+ def to_hash
125
+ value
126
+ end
127
+ end
128
+
129
+ class Ianatoken < Text
130
+ def initialize(val)
131
+ self.value = val
132
+ self.type = "ianatoken"
133
+ end
134
+
135
+ def to_hash
136
+ value
137
+ end
138
+ end
139
+
140
+ class Binary < Text
141
+ def initialize(val)
142
+ self.value = val
143
+ self.type = "binary"
144
+ end
145
+
146
+ def to_hash
147
+ value
148
+ end
149
+ end
150
+
151
+ class Uri < Text
152
+ def initialize(val)
153
+ self.value = val
154
+ self.type = "uri"
155
+ end
156
+
157
+ def to_hash
158
+ value
159
+ end
160
+ end
161
+
162
+ class Calscale < Vobject::PropertyValue
163
+ def initialize(val)
164
+ self.value = val
165
+ self.type = "calscale"
166
+ end
167
+
168
+ def to_s
169
+ value
170
+ end
171
+
172
+ def to_hash
173
+ value
174
+ end
175
+ end
176
+
177
+ class Float < Vobject::PropertyValue
178
+ include Comparable
179
+ def <=>(another)
180
+ value <=> another.value
181
+ end
182
+
183
+ def initialize(val)
184
+ self.value = val
185
+ self.type = "float"
186
+ end
187
+
188
+ def to_s
189
+ value.to_s
190
+ end
191
+
192
+ def to_hash
193
+ value
194
+ end
195
+ end
196
+
197
+ class Integer < Vobject::PropertyValue
198
+ include Comparable
199
+ def <=>(another)
200
+ value <=> another.value
201
+ end
202
+
203
+ def initialize(val)
204
+ self.value = val
205
+ self.type = "integer"
206
+ end
207
+
208
+ def to_s
209
+ value.to_s
210
+ end
211
+
212
+ def to_hash
213
+ value
214
+ end
215
+ end
216
+
217
+ class PercentComplete < Integer
218
+ def initialize(val)
219
+ self.value = val
220
+ self.type = "percentcomplete"
221
+ end
222
+
223
+ def to_hash
224
+ value
225
+ end
226
+ end
227
+
228
+ class Priority < Integer
229
+ def initialize(val)
230
+ self.value = val
231
+ self.type = "priority"
232
+ end
233
+
234
+ def to_hash
235
+ value
236
+ end
237
+ end
238
+
239
+ class Date < Vobject::PropertyValue
240
+ include Comparable
241
+ def <=>(another)
242
+ value <=> another.value
243
+ end
244
+
245
+ def initialize(val)
246
+ self.value = val
247
+ self.type = "date"
248
+ end
249
+
250
+ def to_s
251
+ sprintf("%04d%02d%02d", value.year, value.month, value.day)
252
+ end
253
+
254
+ def to_hash
255
+ value
256
+ end
257
+ end
258
+
259
+ class DateTimeLocal < Vobject::PropertyValue
260
+ include Comparable
261
+ def <=>(another)
262
+ value[:time] <=> another.value[:time]
263
+ end
264
+
265
+ def initialize(val)
266
+ self.value = val.clone
267
+ # val consists of :time && :zone values. If :zone is empty, floating local time (i.e. system local time) is assumed
268
+ self.type = "datetimeLocal"
269
+ value[:time] = if val[:zone].nil? || val[:zone].empty?
270
+ ::Time.local(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
271
+ else
272
+ ::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
273
+ end
274
+ value[:origtime] = value[:time]
275
+ end
276
+
277
+ def to_s
278
+ # ret = sprintf("%04d%02d%02dT%02d%02d%02d", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
279
+ ret = sprintf("%s%s%sT%s%s%s", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
280
+ zone = "Z" if value[:zone] && value[:zone] == "Z"
281
+ ret = ret + zone if !zone.nil?
282
+ ret
283
+ end
284
+
285
+
286
+ def to_hash
287
+ ret = {
288
+ year: value[:year],
289
+ month: value[:month],
290
+ day: value[:day],
291
+ hour: value[:hour],
292
+ min: value[:min],
293
+ sec: value[:sec],
294
+ }
295
+ ret[:zone] = value[:zone] if value[:zone]
296
+ ret
297
+ end
298
+ end
299
+
300
+ class DateTimeUTC < Vobject::PropertyValue
301
+ include Comparable
302
+ def <=>(another)
303
+ value[:time] <=> another.value[:time]
304
+ end
305
+
306
+ def initialize(val)
307
+ self.value = val.clone
308
+ value[:time] = ::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
309
+ value[:origtime] = value[:time]
310
+ end
311
+
312
+ def to_s
313
+ localtime = value[:origtime]
314
+ ret = sprintf("%04d%02d%02dT%02d%02d%02dZ", localtime.year, localtime.month, localtime.day,
315
+ localtime.hour, localtime.min, localtime.sec)
316
+ ret
317
+ end
318
+
319
+ def to_hash
320
+ ret = {
321
+ year: value[:year],
322
+ month: value[:month],
323
+ day: value[:day],
324
+ hour: value[:hour],
325
+ min: value[:min],
326
+ sec: value[:sec],
327
+ }
328
+ ret
329
+ end
330
+ end
331
+
332
+ class Boolean < Vobject::PropertyValue
333
+ def initialize(val)
334
+ self.value = val
335
+ self.type = "boolean"
336
+ end
337
+
338
+ def to_s
339
+ value.to_s
340
+ end
341
+
342
+ def to_hash
343
+ value
344
+ end
345
+
346
+ def to_norm
347
+ value.to_s.upcase
348
+ end
349
+ end
350
+
351
+ class Duration < Vobject::PropertyValue
352
+ def initialize(val)
353
+ self.value = val
354
+ self.type = "duration"
355
+ end
356
+
357
+ def to_s
358
+ ret = "P"
359
+ ret = value[:sign] + ret if value[:sign]
360
+ ret = ret + "#{value[:weeks]}W" if value[:weeks]
361
+ ret = ret + "#{value[:days]}D" if value[:days]
362
+ ret = ret + "T" if value[:hours] || value[:minutes] || value[:seconds]
363
+ ret = ret + "#{value[:hours]}H" if value[:hours]
364
+ ret = ret + "#{value[:minutes]}M" if value[:minutes]
365
+ ret = ret + "#{value[:seconds]}S" if value[:seconds]
366
+ ret
367
+ end
368
+
369
+ def to_hash
370
+ value
371
+ end
372
+ end
373
+
374
+ class Time < Vobject::PropertyValue
375
+ def initialize(val)
376
+ self.value = val
377
+ self.type = "time"
378
+ end
379
+
380
+ def to_s
381
+ ret = "#{value[:hour]}#{value[:min]}#{value[:sec]}"
382
+ ret = ret + "Z" if value[:utc]
383
+ ret
384
+ end
385
+
386
+ def to_hash
387
+ value
388
+ end
389
+ end
390
+
391
+ class Utcoffset < Vobject::PropertyValue
392
+ def initialize(val)
393
+ self.value = val
394
+ self.type = "utcoffset"
395
+ end
396
+
397
+ def to_s
398
+ ret = "#{value[:sign]}#{value[:hr]}#{value[:min]}"
399
+ ret += value[:sec] if value[:sec]
400
+ ret
401
+ end
402
+
403
+ def to_hash
404
+ value
405
+ end
406
+ end
407
+
408
+ class Geovalue < Vobject::PropertyValue
409
+ def initialize(val)
410
+ self.value = val
411
+ self.type = "geovalue"
412
+ end
413
+
414
+ def to_s
415
+ ret = "#{value[:lat]};#{value[:long]}"
416
+ ret
417
+ end
418
+
419
+ def to_hash
420
+ value
421
+ end
422
+ end
423
+
424
+ class Version < Vobject::PropertyValue
425
+ def initialize(val)
426
+ self.value = val
427
+ self.type = "version"
428
+ end
429
+
430
+ def to_s
431
+ value.join(";")
432
+ end
433
+
434
+ def to_hash
435
+ if value.length == 1
436
+ value[0]
437
+ else
438
+ value
439
+ end
440
+ end
441
+ end
442
+
443
+ class Textlist < Vobject::PropertyValue
444
+ def initialize(val)
445
+ self.value = val
446
+ self.type = "textlist"
447
+ end
448
+
449
+ def to_s
450
+ value.map { |m| Text.escape m }.join(",")
451
+ end
452
+
453
+ def to_hash
454
+ value
455
+ end
456
+ end
457
+
458
+ class Periodlist < Vobject::PropertyValue
459
+ def initialize(val)
460
+ self.value = val
461
+ self.type = "periodlist"
462
+ end
463
+
464
+ def to_s
465
+ value.map do |m|
466
+ ret = m[:start].to_s + "/"
467
+ ret += m[:end].to_s if m.has_key? :end
468
+ ret += m[:duration].to_s if m.has_key? :duration
469
+ ret
470
+ end.join(",")
471
+ end
472
+
473
+ def to_hash
474
+ value.map { |m| m.each { |k, v| m[k] = v.to_hash } }
475
+ end
476
+ end
477
+
478
+ class Datelist < Vobject::PropertyValue
479
+ def initialize(val)
480
+ self.value = val
481
+ self.type = "datelist"
482
+ end
483
+
484
+ def to_s
485
+ value.map(&:to_s).join(",")
486
+ end
487
+
488
+ def to_hash
489
+ value.map(&:to_hash)
490
+ end
491
+ end
492
+
493
+ class Datetimelist < Vobject::PropertyValue
494
+ def initialize(val)
495
+ self.value = val
496
+ self.type = "datetimelist"
497
+ end
498
+
499
+ def to_s
500
+ value.map(&:to_s).join(",")
501
+ end
502
+
503
+ def to_hash
504
+ value.map(&:to_hash)
505
+ end
506
+ end
507
+
508
+ class Datetimeutclist < Vobject::PropertyValue
509
+ def initialize(val)
510
+ self.value = val
511
+ self.type = "datetimeutclist"
512
+ end
513
+
514
+ def to_s
515
+ value.map(&:to_s).join(",")
516
+ end
517
+
518
+ def to_hash
519
+ value.map(&:to_hash)
520
+ end
521
+ end
522
+
523
+ class Requeststatusvalue < Vobject::PropertyValue
524
+ def initialize(val)
525
+ self.value = val
526
+ self.type = "requeststatusvalue"
527
+ end
528
+
529
+ def to_s
530
+ ret = "#{value[:statcode]};#{value[:statdesc]}"
531
+ ret += ";#{value[:extdata]}" if value[:extdata]
532
+ ret
533
+ end
534
+
535
+ def to_hash
536
+ value
537
+ end
538
+ end
539
+
540
+ class Recur < Vobject::PropertyValue
541
+ def initialize(val)
542
+ self.value = val
543
+ self.type = "recur"
544
+ end
545
+
546
+ def to_s
547
+ ret = []
548
+ value.each do |k, v|
549
+ ret << "#{k.to_s.upcase}=#{valencode(k, v)}"
550
+ end
551
+ ret.join(";")
552
+ end
553
+
554
+ def to_hash
555
+ ret = {}
556
+ value.each do |k, v|
557
+ ret[k] = if v.respond_to?(:to_hash)
558
+ v.to_hash
559
+ else
560
+ v
561
+ end
562
+ end
563
+ ret
564
+ end
565
+
566
+ private
567
+
568
+ def valencode(k, v)
569
+ case k
570
+ when :bysetpos, :byyearday
571
+ v.map do |x|
572
+ ret = x[:ordyrday]
573
+ ret = x[:sign] + ret if x[:sign]
574
+ ret
575
+ end.join(",")
576
+ when :byweekno
577
+ v.map do |x|
578
+ ret = x[:ordwk]
579
+ ret = x[:sign] + ret if x[:sign]
580
+ ret
581
+ end.join(",")
582
+ when :bymonthday
583
+ v.map do |x|
584
+ ret = x[:ordmoday]
585
+ ret = x[:sign] + ret if x[:sign]
586
+ ret
587
+ end.join(",")
588
+ when :byday
589
+ v.map do |x|
590
+ ret = x[:weekday]
591
+ ret = x[:ordwk] + ret if x[:ordwk]
592
+ ret = x[:sign] + ret if x[:sign]
593
+ ret
594
+ end.join(",")
595
+ when :bymonth, :byhour, :byminute, :bysecond
596
+ v.join(",")
597
+ when :enddate
598
+ v.to_s
599
+ else
600
+ v
601
+ end
602
+ end
603
+ end
604
+ end
605
+ end
606
+ end