vobject 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.
- checksums.yaml +7 -0
- data/.github/workflows/macos.yml +38 -0
- data/.github/workflows/ubuntu.yml +56 -0
- data/.github/workflows/windows.yml +40 -0
- data/.gitignore +9 -0
- data/.hound.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.tb.yml +650 -0
- data/.rubocop.yml +1077 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +25 -0
- data/README.adoc +151 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/c.rb +173 -0
- data/lib/error.rb +19 -0
- data/lib/vcalendar.rb +77 -0
- data/lib/vcard.rb +67 -0
- data/lib/vobject.rb +25 -0
- data/lib/vobject/component.rb +126 -0
- data/lib/vobject/parameter.rb +116 -0
- data/lib/vobject/parametervalue.rb +26 -0
- data/lib/vobject/property.rb +162 -0
- data/lib/vobject/propertyvalue.rb +46 -0
- data/lib/vobject/vcalendar/component.rb +106 -0
- data/lib/vobject/vcalendar/grammar.rb +595 -0
- data/lib/vobject/vcalendar/paramcheck.rb +259 -0
- data/lib/vobject/vcalendar/propertyparent.rb +98 -0
- data/lib/vobject/vcalendar/propertyvalue.rb +606 -0
- data/lib/vobject/vcalendar/typegrammars.rb +605 -0
- data/lib/vobject/vcard/v3_0/component.rb +40 -0
- data/lib/vobject/vcard/v3_0/grammar.rb +175 -0
- data/lib/vobject/vcard/v3_0/paramcheck.rb +110 -0
- data/lib/vobject/vcard/v3_0/parameter.rb +17 -0
- data/lib/vobject/vcard/v3_0/property.rb +18 -0
- data/lib/vobject/vcard/v3_0/propertyvalue.rb +401 -0
- data/lib/vobject/vcard/v3_0/typegrammars.rb +425 -0
- data/lib/vobject/vcard/v4_0/component.rb +40 -0
- data/lib/vobject/vcard/v4_0/grammar.rb +224 -0
- data/lib/vobject/vcard/v4_0/paramcheck.rb +269 -0
- data/lib/vobject/vcard/v4_0/parameter.rb +18 -0
- data/lib/vobject/vcard/v4_0/property.rb +63 -0
- data/lib/vobject/vcard/v4_0/propertyvalue.rb +404 -0
- data/lib/vobject/vcard/v4_0/typegrammars.rb +539 -0
- data/lib/vobject/version.rb +3 -0
- data/vobject.gemspec +32 -0
- metadata +174 -0
data/lib/vcalendar.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require "vobject"
|
|
2
|
+
require "vobject/component"
|
|
3
|
+
require "vobject/vcalendar/component"
|
|
4
|
+
require "vobject/vcalendar/grammar"
|
|
5
|
+
require "json"
|
|
6
|
+
|
|
7
|
+
class Vcalendar < Vobject::Component
|
|
8
|
+
attr_accessor :comp_name, :children, :version
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
def parse(vcf, strict)
|
|
12
|
+
Vobject::Component::Vcalendar.parse(vcf, strict)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(key, cs, err)
|
|
17
|
+
super key, cs, err
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def child_class(key, val)
|
|
21
|
+
base_class = if key == :VTODO
|
|
22
|
+
Vobject::Component::Vcalendar::ToDo
|
|
23
|
+
elsif key == :VFREEBUSY
|
|
24
|
+
Vobject::Component::Vcalendar::FreeBusy
|
|
25
|
+
elsif key == :JOURNAL
|
|
26
|
+
Vobject::Component::Vcalendar::Journal
|
|
27
|
+
elsif key == :STANDARD
|
|
28
|
+
Vobject::Component::Vcalendar::Timezone::Standard
|
|
29
|
+
elsif key == :DAYLIGHT
|
|
30
|
+
Vobject::Component::Vcalendar::Timezone::Daylight
|
|
31
|
+
elsif key == :VTIMEZONE
|
|
32
|
+
Vobject::Component::Vcalendar::Timezone
|
|
33
|
+
elsif key == :VEVENT
|
|
34
|
+
Vobject::Component::Vcalendar::Event
|
|
35
|
+
elsif key == :VALARM
|
|
36
|
+
Vobject::Component::Vcalendar::Alarm
|
|
37
|
+
elsif key == :VAVAILABILITY
|
|
38
|
+
Vobject::Component::Vcalendar::Vavailability
|
|
39
|
+
elsif key == :AVAILABLE
|
|
40
|
+
Vobject::Component::Vcalendar::Vavailability::Available
|
|
41
|
+
elsif !(val.is_a?(Hash) && !val.has_key?(:value))
|
|
42
|
+
property_base_class
|
|
43
|
+
else
|
|
44
|
+
Vobject::Component::Vcalendar
|
|
45
|
+
end
|
|
46
|
+
return base_class if [:CLASS, :OBJECT, :METHOD].include?
|
|
47
|
+
camelized_key = key.to_s.downcase.split("_").map(&:capitalize).join("")
|
|
48
|
+
base_class.const_get(camelized_key) rescue base_class
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def raise_invalid_parsing
|
|
54
|
+
raise "Vobject component parse failed"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class Vobject::Component::Vcalendar::ToDo < Vobject::Component::Vcalendar
|
|
59
|
+
end
|
|
60
|
+
class Vobject::Component::Vcalendar::Freebusy < Vobject::Component::Vcalendar
|
|
61
|
+
end
|
|
62
|
+
class Vobject::Component::Vcalendar::Journal < Vobject::Component::Vcalendar
|
|
63
|
+
end
|
|
64
|
+
class Vobject::Component::Vcalendar::Timezone < Vobject::Component::Vcalendar
|
|
65
|
+
end
|
|
66
|
+
class Vobject::Component::Vcalendar::Timezone::Standard < Vobject::Component::Vcalendar::Timezone
|
|
67
|
+
end
|
|
68
|
+
class Vobject::Component::Vcalendar::Timezone::Daylight < Vobject::Component::Vcalendar::Timezone
|
|
69
|
+
end
|
|
70
|
+
class Vobject::Component::Vcalendar::Event < Vobject::Component::Vcalendar
|
|
71
|
+
end
|
|
72
|
+
class Vobject::Component::Vcalendar::Alarm < Vobject::Component::Vcalendar
|
|
73
|
+
end
|
|
74
|
+
class Vobject::Component::Vcalendar::Vavailability < Vobject::Component::Vcalendar
|
|
75
|
+
end
|
|
76
|
+
# class Vobject::Component::Vcalendar::Vavailability::Available < Vobject::Component::Vcalendar::Vavailability
|
|
77
|
+
# end
|
data/lib/vcard.rb
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require "vobject"
|
|
2
|
+
require "vobject/component"
|
|
3
|
+
|
|
4
|
+
class Vcard < Vobject::Component
|
|
5
|
+
attr_accessor :version
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def blank(version)
|
|
9
|
+
new VERSION: { value: version }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def decode(vcard_str, version = nil)
|
|
13
|
+
version_str = version.nil? ? "4.0" : /\nVERSION:([^\n\r]+)/i.match(vcard_str)[1]
|
|
14
|
+
blank(version_str).parse(vcard_str)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def parse(vcf, version, strict)
|
|
18
|
+
hash = version == "3.0" ? Vcard::V3_0::Component.parse(vcf, strict) : Vcard::V4_0::Component.parse(vcf, strict)
|
|
19
|
+
# comp_name = hash.keys.first
|
|
20
|
+
# return self.new(comp_name, hash[:vobject][comp_name], hash[:errors] )
|
|
21
|
+
hash
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def raise_invalid_parsing
|
|
27
|
+
raise "vCard parse failed"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize(version)
|
|
32
|
+
self.version = version
|
|
33
|
+
super VCARD: { VERSION: { value: version } }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def name
|
|
39
|
+
:VCARD
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def property_base_class
|
|
43
|
+
version == "3.0" ? Vcard::V3_0::Property : Vcard::V4_0::Property
|
|
44
|
+
# version_class.const_get(:Property)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def component_base_class
|
|
48
|
+
version == "3.0" ? Vcard::V3_0::Component : Vcard::V4_0::Component
|
|
49
|
+
# version_class.const_get(:Component)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def require_dir(dir)
|
|
54
|
+
base = File.expand_path("../", __FILE__)
|
|
55
|
+
Dir.glob(File.join(base, dir, "**", "*.rb")).each do |path|
|
|
56
|
+
require path.gsub(/\.rb\Z/, "")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
require "vobject/vcard/v4_0/component"
|
|
61
|
+
require "vobject/vcard/v4_0/property"
|
|
62
|
+
require_dir "vobject/vcard/v4_0/component"
|
|
63
|
+
require_dir "vobject/vcard/v4_0/property"
|
|
64
|
+
require "vobject/vcard/v3_0/component"
|
|
65
|
+
require "vobject/vcard/v3_0/property"
|
|
66
|
+
require_dir "vobject/vcard/v3_0/component"
|
|
67
|
+
require_dir "vobject/vcard/v3_0/property"
|
data/lib/vobject.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Vobject
|
|
2
|
+
class << self
|
|
3
|
+
MAX_LINE_WIDTH = 75
|
|
4
|
+
def unfold(str)
|
|
5
|
+
str.gsub(/(\r|\n|\r\n)[ \t]/, "")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# This implements the line folding as specified in
|
|
9
|
+
# http://tools.ietf.org/html/rfc6350#section-3.2
|
|
10
|
+
# NOTE: the "line" here is not including the trailing \n
|
|
11
|
+
def fold_line(line)
|
|
12
|
+
folded_line = line[0, MAX_LINE_WIDTH]
|
|
13
|
+
remainder_line = line[MAX_LINE_WIDTH, line.length - MAX_LINE_WIDTH] || ""
|
|
14
|
+
|
|
15
|
+
max_width = MAX_LINE_WIDTH - 1
|
|
16
|
+
|
|
17
|
+
(0..((remainder_line.length - 1) / max_width)).each do |i|
|
|
18
|
+
folded_line << "\n "
|
|
19
|
+
folded_line << remainder_line[i * max_width, max_width]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
folded_line
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require "vobject"
|
|
2
|
+
require "vobject/property"
|
|
3
|
+
require "vobject/vcalendar/grammar"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
class Vobject::Component
|
|
7
|
+
attr_accessor :comp_name, :children, :multiple_components, :errors, :norm
|
|
8
|
+
|
|
9
|
+
def <=>(another)
|
|
10
|
+
me = self.to_norm
|
|
11
|
+
o = another.to_norm
|
|
12
|
+
me <=> o
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def blank(version)
|
|
16
|
+
ingest VOBJECT: { VERSION: { value: version } }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize(key, cs, err)
|
|
20
|
+
self.comp_name = key
|
|
21
|
+
raise_invalid_initialization if key != name
|
|
22
|
+
self.children = []
|
|
23
|
+
if cs.nil?
|
|
24
|
+
else
|
|
25
|
+
cs.each_key do |k|
|
|
26
|
+
val = cs[k]
|
|
27
|
+
# iteration of array || hash values is making the value a key!
|
|
28
|
+
next if k.class == Array
|
|
29
|
+
next if k.class == Hash
|
|
30
|
+
cc = child_class(k, val)
|
|
31
|
+
if val.is_a?(Hash) && val.has_key?(:component)
|
|
32
|
+
val[:component].each do |x|
|
|
33
|
+
children << cc.new(k, x, [])
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
children << cc.new(k, val)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
self.errors = err.select { |e| !e.nil? }
|
|
41
|
+
self.norm = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def get_errors
|
|
45
|
+
errors
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def child_class(key, val)
|
|
49
|
+
base_class = if val.is_a?(Hash) && val.has_key?(:component)
|
|
50
|
+
component_base_class
|
|
51
|
+
elsif !(val.is_a?(Hash) && !val.has_key?(:value))
|
|
52
|
+
property_base_class
|
|
53
|
+
else
|
|
54
|
+
component_base_class
|
|
55
|
+
end
|
|
56
|
+
return base_class if [:CLASS, :OBJECT, :METHOD].include? key
|
|
57
|
+
camelized_key = key.to_s.downcase.split("_").map(&:capitalize).join("")
|
|
58
|
+
base_class.const_get(camelized_key) rescue base_class
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def to_s
|
|
62
|
+
s = "BEGIN:#{name}\n"
|
|
63
|
+
children.each do |c|
|
|
64
|
+
s << c.to_s
|
|
65
|
+
end
|
|
66
|
+
s << "END:#{name}\n"
|
|
67
|
+
s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_norm
|
|
71
|
+
if norm.nil?
|
|
72
|
+
s = "BEGIN:#{name.upcase}\n"
|
|
73
|
+
properties = children.select { |c| c.is_a? Vobject::Property }
|
|
74
|
+
components = children.select { |c| not c.is_a? Vobject::Property }
|
|
75
|
+
# create to_norm in advance
|
|
76
|
+
properties.each { |p| p.to_norm }
|
|
77
|
+
properties.sort.each do |p|
|
|
78
|
+
s << p.to_norm
|
|
79
|
+
end
|
|
80
|
+
components.sort.each { |p| s << p.to_norm }
|
|
81
|
+
s << "END:#{name.upcase}\n"
|
|
82
|
+
norm = s
|
|
83
|
+
end
|
|
84
|
+
norm
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def to_hash
|
|
88
|
+
a = {}
|
|
89
|
+
children.each do |c|
|
|
90
|
+
if c.is_a?(Vobject::Component)
|
|
91
|
+
a = a.merge(c.to_hash) { |_, old, new| [old, new].flatten }
|
|
92
|
+
elsif c.is_a?(Vobject::Property)
|
|
93
|
+
a = a.merge(c.to_hash) { |_, old, new| [old, new].flatten }
|
|
94
|
+
else
|
|
95
|
+
a[c.name] = c.to_hash
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
{ comp_name => a }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def to_json
|
|
102
|
+
to_hash.to_json
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def name
|
|
106
|
+
comp_name
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def property_base_class
|
|
112
|
+
Vobject::Property
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def component_base_class
|
|
116
|
+
Vobject::Component
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def parameter_base_class
|
|
120
|
+
Vobject::Parameter
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def raise_invalid_initialization
|
|
124
|
+
raise "vObject component initialization failed"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module Vobject
|
|
2
|
+
class Parameter
|
|
3
|
+
attr_accessor :param_name, :value, :multiple, :norm
|
|
4
|
+
|
|
5
|
+
def <=>(another)
|
|
6
|
+
self.to_norm <=> another.to_norm
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(key, options)
|
|
10
|
+
self.param_name = key
|
|
11
|
+
if options.class == Array
|
|
12
|
+
self.multiple = []
|
|
13
|
+
options.each do |v|
|
|
14
|
+
multiple << parameter_base_class.new(key, v)
|
|
15
|
+
self.param_name = key
|
|
16
|
+
end
|
|
17
|
+
else
|
|
18
|
+
self.value = options
|
|
19
|
+
end
|
|
20
|
+
norm = nil
|
|
21
|
+
raise_invalid_initialization(key, name) if key != name
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_s
|
|
25
|
+
# we made param names have underscore instead of dash as symbols
|
|
26
|
+
line = param_name.to_s.tr("_", "-")
|
|
27
|
+
line << "="
|
|
28
|
+
if multiple
|
|
29
|
+
arr = []
|
|
30
|
+
multiple.each { |v| arr << to_s_line(v.value.to_s) }
|
|
31
|
+
line << arr.join(",")
|
|
32
|
+
else
|
|
33
|
+
line << to_s_line(value.to_s)
|
|
34
|
+
end
|
|
35
|
+
line
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_s_line(val)
|
|
39
|
+
# RFC 6868
|
|
40
|
+
val = val.to_s.gsub(/\^/, "^^").gsub(/\n/, "^n").gsub(/"/, "^'")
|
|
41
|
+
if val =~ /[:;,]/
|
|
42
|
+
val = '"' + val + '"'
|
|
43
|
+
end
|
|
44
|
+
val
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_norm
|
|
48
|
+
if norm.nil?
|
|
49
|
+
line = param_name.to_s.tr("_", "-").upcase
|
|
50
|
+
line << "="
|
|
51
|
+
if multiple
|
|
52
|
+
arr = []
|
|
53
|
+
multiple.sort.each { |v| arr << to_norm_line(v.value) }
|
|
54
|
+
line << arr.join(",")
|
|
55
|
+
else
|
|
56
|
+
line << to_norm_line(value)
|
|
57
|
+
end
|
|
58
|
+
norm = line
|
|
59
|
+
end
|
|
60
|
+
norm
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_norm_line(val)
|
|
64
|
+
# RFC 6868
|
|
65
|
+
val = val.to_s.gsub(/\^/, "^^").gsub(/\n/, "^n").gsub(/"/, "^'")
|
|
66
|
+
#if val =~ /[:;,]/
|
|
67
|
+
val = '"' + val + '"'
|
|
68
|
+
#end
|
|
69
|
+
val
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_hash
|
|
73
|
+
if multiple
|
|
74
|
+
val = []
|
|
75
|
+
multiple.each do |c|
|
|
76
|
+
val << c.value
|
|
77
|
+
end
|
|
78
|
+
{ param_name => val }
|
|
79
|
+
else
|
|
80
|
+
{ param_name => value }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def name
|
|
87
|
+
param_name
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def parse_value(value)
|
|
91
|
+
parse_method = :"parse_#{value_type}_value"
|
|
92
|
+
parse_method = respond_to?(parse_method, true) ? parse_method : :parse_text_value
|
|
93
|
+
send(parse_method, value)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def parse_text_value(value)
|
|
97
|
+
value
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def value_type
|
|
101
|
+
(params || {})[:VALUE] || default_value_type
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def default_value_type
|
|
105
|
+
"text"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parameter_base_class
|
|
109
|
+
Vobject::Parameter
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def raise_invalid_initialization(key, name)
|
|
113
|
+
raise "vObject property initialization failed (#{key}, #{name})"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Vobject
|
|
2
|
+
class ParameterValue
|
|
3
|
+
def initialize(val)
|
|
4
|
+
self.value = val
|
|
5
|
+
end
|
|
6
|
+
# raise_invalid_initialization if key != name
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_s
|
|
10
|
+
value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def name
|
|
16
|
+
prop_name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def default_value_type
|
|
20
|
+
"text"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def raise_invalid_initialization
|
|
24
|
+
raise "vObject property initialization failed"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require "vobject"
|
|
2
|
+
require "vobject/parameter"
|
|
3
|
+
|
|
4
|
+
class Vobject::Property
|
|
5
|
+
attr_accessor :group, :prop_name, :params, :value, :multiple, :norm
|
|
6
|
+
|
|
7
|
+
def <=>(another)
|
|
8
|
+
if self.prop_name =~ /^VERSION$/i
|
|
9
|
+
-1
|
|
10
|
+
elsif another.prop_name =~ /^VERSION$/i
|
|
11
|
+
1
|
|
12
|
+
else
|
|
13
|
+
self.to_norm <=> another.to_norm
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(key, options)
|
|
18
|
+
if options.class == Array
|
|
19
|
+
self.multiple = []
|
|
20
|
+
options.each do |v|
|
|
21
|
+
multiple << property_base_class.new(key, v)
|
|
22
|
+
self.prop_name = key
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
self.prop_name = key
|
|
26
|
+
if options.nil? || options.empty?
|
|
27
|
+
self.group = nil
|
|
28
|
+
self.params = []
|
|
29
|
+
self.value = nil
|
|
30
|
+
else
|
|
31
|
+
self.group = options[:group]
|
|
32
|
+
self.prop_name = key
|
|
33
|
+
unless options[:params].nil? || options[:params].empty?
|
|
34
|
+
self.params = []
|
|
35
|
+
options[:params].each do |k, v|
|
|
36
|
+
params << parameter_base_class.new(k, v)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
# self.value = parse_value(options[:value])
|
|
40
|
+
self.value = options[:value]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
self.norm = nil
|
|
44
|
+
raise_invalid_initialization if key != name
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
if multiple.nil? || multiple.empty?
|
|
49
|
+
ret = to_s_line
|
|
50
|
+
else
|
|
51
|
+
arr = []
|
|
52
|
+
multiple.each do |x|
|
|
53
|
+
arr << x.to_s_line
|
|
54
|
+
end
|
|
55
|
+
ret = arr.join("")
|
|
56
|
+
end
|
|
57
|
+
ret
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_s_line
|
|
61
|
+
line = group ? "#{group}." : ""
|
|
62
|
+
line << name.to_s.tr("_", "-")
|
|
63
|
+
|
|
64
|
+
(params || {}).each do |p|
|
|
65
|
+
line << ";#{p}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
line << ":#{value}"
|
|
69
|
+
|
|
70
|
+
line = Vobject::fold_line(line) << "\n"
|
|
71
|
+
|
|
72
|
+
line
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_norm
|
|
76
|
+
if @norm.nil?
|
|
77
|
+
if multiple.nil? || multiple.empty?
|
|
78
|
+
ret = to_norm_line
|
|
79
|
+
else
|
|
80
|
+
arr = []
|
|
81
|
+
multiple.sort.each do |x|
|
|
82
|
+
arr << x.to_norm_line
|
|
83
|
+
end
|
|
84
|
+
ret = arr.join("")
|
|
85
|
+
end
|
|
86
|
+
@norm = ret
|
|
87
|
+
end
|
|
88
|
+
@norm
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def to_norm_line
|
|
92
|
+
line = group ? "#{group}." : ""
|
|
93
|
+
line << name.to_s.tr("_", "-").upcase
|
|
94
|
+
|
|
95
|
+
(params || {}).sort.each do |p|
|
|
96
|
+
line << ";#{p.to_norm}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
line << ":#{value.to_norm}"
|
|
100
|
+
|
|
101
|
+
line = Vobject::fold_line(line) << "\n"
|
|
102
|
+
|
|
103
|
+
line
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def to_hash
|
|
108
|
+
ret = {}
|
|
109
|
+
if multiple
|
|
110
|
+
ret[prop_name] = []
|
|
111
|
+
multiple.each do |c|
|
|
112
|
+
ret[prop_name] = ret[prop_name] << c.to_hash[prop_name]
|
|
113
|
+
end
|
|
114
|
+
else
|
|
115
|
+
ret = {prop_name => { value: value.to_hash } }
|
|
116
|
+
ret[prop_name][:group] = group unless group.nil?
|
|
117
|
+
if params
|
|
118
|
+
ret[prop_name][:params] = {}
|
|
119
|
+
params.each do |p|
|
|
120
|
+
ret[prop_name][:params] = ret[prop_name][:params].merge p.to_hash
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
ret
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
def name
|
|
130
|
+
prop_name
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def parse_value(value)
|
|
134
|
+
parse_method = :"parse_#{value_type}_value"
|
|
135
|
+
parse_method = respond_to?(parse_method, true) ? parse_method : :parse_text_value
|
|
136
|
+
send(parse_method, value)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def parse_text_value(value)
|
|
140
|
+
value
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def value_type
|
|
144
|
+
params ? params[0].value : default_value_type
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def default_value_type
|
|
148
|
+
"text"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def property_base_class
|
|
152
|
+
Vobject::Property
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def parameter_base_class
|
|
156
|
+
Vobject::Parameter
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def raise_invalid_initialization
|
|
160
|
+
raise "vObject property initialization failed"
|
|
161
|
+
end
|
|
162
|
+
end
|