zimbra-soap-api 0.0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.irbrc +6 -0
  4. data/Gemfile +6 -0
  5. data/README +21 -0
  6. data/Rakefile +1 -0
  7. data/lib/zimbra.rb +94 -0
  8. data/lib/zimbra/account.rb +94 -0
  9. data/lib/zimbra/acl.rb +63 -0
  10. data/lib/zimbra/alias.rb +4 -0
  11. data/lib/zimbra/appointment.rb +274 -0
  12. data/lib/zimbra/appointment/alarm.rb +101 -0
  13. data/lib/zimbra/appointment/attendee.rb +97 -0
  14. data/lib/zimbra/appointment/invite.rb +360 -0
  15. data/lib/zimbra/appointment/recur_exception.rb +83 -0
  16. data/lib/zimbra/appointment/recur_rule.rb +184 -0
  17. data/lib/zimbra/appointment/reply.rb +91 -0
  18. data/lib/zimbra/auth.rb +46 -0
  19. data/lib/zimbra/base.rb +217 -0
  20. data/lib/zimbra/calendar.rb +27 -0
  21. data/lib/zimbra/common_elements.rb +51 -0
  22. data/lib/zimbra/cos.rb +124 -0
  23. data/lib/zimbra/delegate_auth_token.rb +49 -0
  24. data/lib/zimbra/directory.rb +175 -0
  25. data/lib/zimbra/distribution_list.rb +147 -0
  26. data/lib/zimbra/domain.rb +63 -0
  27. data/lib/zimbra/ext/handsoap_curb_driver.rb +21 -0
  28. data/lib/zimbra/ext/hash.rb +72 -0
  29. data/lib/zimbra/ext/string.rb +10 -0
  30. data/lib/zimbra/extra/date_helpers.rb +111 -0
  31. data/lib/zimbra/folder.rb +100 -0
  32. data/lib/zimbra/handsoap_account_service.rb +44 -0
  33. data/lib/zimbra/handsoap_service.rb +75 -0
  34. data/lib/zimbra/version.rb +3 -0
  35. data/spec/fixtures/xml_api_requests/appointments/create.xml +84 -0
  36. data/spec/fixtures/xml_api_responses/alarms/15_minutes_before.xml +26 -0
  37. data/spec/fixtures/xml_api_responses/alarms/using_all_intervals.xml +26 -0
  38. data/spec/fixtures/xml_api_responses/appointments/appointment_response_1.xml +40 -0
  39. data/spec/fixtures/xml_api_responses/attendees/one_attendee_and_one_reply.xml +27 -0
  40. data/spec/fixtures/xml_api_responses/attendees/three_attendees_response_1.xml +30 -0
  41. data/spec/fixtures/xml_api_responses/multiple_invites/recurring_with_exceptions.xml +109 -0
  42. data/spec/fixtures/xml_api_responses/recur_rules/day_27_of_every_2_months.xml +27 -0
  43. data/spec/fixtures/xml_api_responses/recur_rules/every_2_days.xml +26 -0
  44. data/spec/fixtures/xml_api_responses/recur_rules/every_3_weeks_on_tuesday_and_friday.xml +30 -0
  45. data/spec/fixtures/xml_api_responses/recur_rules/every_day_50_instances.xml +27 -0
  46. data/spec/fixtures/xml_api_responses/recur_rules/every_monday_wednesday_friday.xml +31 -0
  47. data/spec/fixtures/xml_api_responses/recur_rules/every_tuesday.xml +29 -0
  48. data/spec/fixtures/xml_api_responses/recur_rules/every_weekday_with_end_date.xml +34 -0
  49. data/spec/fixtures/xml_api_responses/recur_rules/every_year_on_february_2.xml +28 -0
  50. data/spec/fixtures/xml_api_responses/recur_rules/first_day_of_every_month.xml +36 -0
  51. data/spec/fixtures/xml_api_responses/recur_rules/first_monday_of_every_february.xml +31 -0
  52. data/spec/fixtures/xml_api_responses/recur_rules/first_weekend_day_of_every_month.xml +31 -0
  53. data/spec/fixtures/xml_api_responses/recur_rules/last_day_of_every_month.xml +36 -0
  54. data/spec/fixtures/xml_api_responses/recur_rules/second_day_of_every_2_months.xml +36 -0
  55. data/spec/fixtures/xml_api_responses/recur_rules/second_wednesday_of_every_month.xml +29 -0
  56. data/spec/fixtures/xml_api_responses/recur_rules/weekly_with_an_exception.xml +44 -0
  57. data/spec/spec_helper.rb +32 -0
  58. data/spec/zimbra/acl_spec.rb +11 -0
  59. data/spec/zimbra/appointment/alarm_spec.rb +33 -0
  60. data/spec/zimbra/appointment/invite_spec.rb +62 -0
  61. data/spec/zimbra/appointment/recur_rule_spec.rb +307 -0
  62. data/spec/zimbra/appointment_spec.rb +175 -0
  63. data/spec/zimbra/common_elements_spec.rb +33 -0
  64. data/spec/zimbra/distribution_list_spec.rb +54 -0
  65. data/zimbra.gemspec +28 -0
  66. metadata +197 -0
@@ -0,0 +1,83 @@
1
+ module Zimbra
2
+ class Appointment
3
+ class RecurException
4
+ class << self
5
+ def new_from_zimbra_attributes(zimbra_attributes)
6
+ return nil unless zimbra_attributes
7
+ new(parse_zimbra_attributes(zimbra_attributes))
8
+ end
9
+
10
+ def parse_zimbra_attributes(zimbra_attributes)
11
+ zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
12
+
13
+ {
14
+ :recurrence_id => zimbra_attributes[:d],
15
+ :timezone => zimbra_attributes[:tz],
16
+ :range_type => zimbra_attributes[:rangeType]
17
+ }
18
+ end
19
+ end
20
+
21
+ ATTRS = [
22
+ :recurrence_id,
23
+ :timezone,
24
+ :range_type
25
+ ] unless const_defined?(:ATTRS)
26
+
27
+ attr_accessor *ATTRS
28
+
29
+ def range_type=(val)
30
+ @range_type = parse_range_type(val)
31
+ end
32
+
33
+ def initialize(args = {})
34
+ self.attributes = args
35
+ end
36
+
37
+ # take attributes by the xml name or our more descriptive name
38
+ def attributes=(args = {})
39
+ ATTRS.each do |attr_name|
40
+ self.send(:"#{attr_name}=", (args[attr_name] || args[attr_name.to_s]))
41
+ end
42
+ end
43
+
44
+ def to_hash(options = {})
45
+ hash = ATTRS.inject({}) do |attr_hash, attr_name|
46
+ attr_hash[attr_name] = self.send(:"#{attr_name}")
47
+ attr_hash
48
+ end
49
+ hash.reject! { |key, value| options[:except].include?(key.to_sym) || options[:except].include?(key.to_s) } if options[:except]
50
+ hash.reject! { |key, value| !options[:only].include?(key.to_sym) && !options[:only].include?(key.to_s) } if options[:only]
51
+ hash
52
+ end
53
+
54
+ def range_type_to_zimbra
55
+ possible_range_type_values.find { |k, v| v == range_type }.first rescue range_type
56
+ end
57
+
58
+ def create_xml(document)
59
+ document.add "exceptId" do |except_element|
60
+ except_element.set_attr "d", recurrence_id
61
+ except_element.set_attr "tz", timezone
62
+ except_element.set_attr "rangeType", range_type_to_zimbra if range_type
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def possible_range_type_values
69
+ @possible_range_type_values ||= {
70
+ 1 => :none,
71
+ 2 => :this_and_future,
72
+ 3 => :this_and_prior
73
+ }
74
+ end
75
+
76
+ def parse_range_type(val)
77
+ int_val = val.to_int rescue nil
78
+
79
+ possible_range_type_values[int_val] || val
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,184 @@
1
+ module Zimbra
2
+ class Appointment
3
+ class RecurRule
4
+ class << self
5
+ def new_from_zimbra_attributes(zimbra_attributes)
6
+ return nil unless zimbra_attributes
7
+ new(parse_zimbra_attributes(zimbra_attributes))
8
+ end
9
+
10
+ def parse_zimbra_attributes(zimbra_attributes)
11
+ attrs = {}
12
+
13
+ zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
14
+ zimbra_attributes = zimbra_attributes[:add][:rule]
15
+
16
+ attrs[:frequency] = zimbra_attributes[:attributes][:freq] if zimbra_attributes[:attributes]
17
+ attrs[:until_date] = zimbra_attributes[:until][:attributes][:d] if zimbra_attributes[:until]
18
+ attrs[:interval] = zimbra_attributes[:interval][:attributes][:ival] if zimbra_attributes[:interval]
19
+ attrs[:count] = zimbra_attributes[:count][:attributes][:num] if zimbra_attributes[:count]
20
+
21
+ if zimbra_attributes[:bysetpos]
22
+ attrs[:by_set_position] = zimbra_attributes[:bysetpos][:attributes][:poslist]
23
+ attrs[:by_set_position] = [attrs[:by_set_position]] unless attrs[:by_set_position].is_a?(Array)
24
+ end
25
+
26
+ if zimbra_attributes[:byday] && zimbra_attributes[:byday][:wkday] && zimbra_attributes[:byday][:wkday].is_a?(Array)
27
+ attrs[:by_day] = zimbra_attributes[:byday][:wkday].collect do |wkday|
28
+ wkday = Zimbra::Hash.symbolize_keys(wkday, true)
29
+ wkday_hash = { day: wkday[:attributes][:day] }
30
+ wkday_hash[:week_number] = wkday[:attributes][:ordwk] if wkday[:attributes][:ordwk]
31
+ wkday_hash
32
+ end
33
+ elsif zimbra_attributes[:byday] && zimbra_attributes[:byday][:wkday]
34
+ day_hash = { day: zimbra_attributes[:byday][:wkday][:attributes][:day] }
35
+ day_hash[:week_number] = zimbra_attributes[:byday][:wkday][:attributes][:ordwk] if zimbra_attributes[:byday][:wkday][:attributes][:ordwk]
36
+ attrs[:by_day] = [day_hash]
37
+ end
38
+
39
+ if zimbra_attributes[:bymonth]
40
+ attrs[:by_month] = zimbra_attributes[:bymonth][:attributes][:molist]
41
+ attrs[:by_month] = [attrs[:by_month]] unless attrs[:by_month].is_a?(Array)
42
+ end
43
+
44
+ if zimbra_attributes[:bymonthday]
45
+ attrs[:by_month_day] = zimbra_attributes[:bymonthday][:attributes][:modaylist]
46
+ attrs[:by_month_day] = [attrs[:by_month_day]] unless attrs[:by_month_day].is_a?(Array)
47
+ end
48
+
49
+ attrs
50
+ end
51
+ end
52
+
53
+ ATTRS = [
54
+ :frequency,
55
+ :interval,
56
+ :by_day,
57
+ :by_month,
58
+ :by_month_day,
59
+ :count,
60
+ :until_date,
61
+ :by_set_position
62
+ ] unless const_defined?(:ATTRS)
63
+
64
+ attr_accessor *ATTRS
65
+
66
+ def initialize(args = {})
67
+ self.attributes = args
68
+ end
69
+
70
+ # take attributes by the xml name or our more descriptive name
71
+ def attributes=(args = {})
72
+ ATTRS.each do |attr_name|
73
+ if args.has_key?(attr_name)
74
+ self.send(:"#{attr_name}=", args[attr_name])
75
+ elsif args.has_key?(attr_name.to_s)
76
+ self.send(:"#{attr_name}=", args[attr_name.to_s])
77
+ end
78
+ end
79
+ end
80
+
81
+ def frequency=(val)
82
+ frequency = Zimbra::DateHelpers::Frequency.find(val).name
83
+ @frequency = frequency || val
84
+ end
85
+
86
+ def frequency_to_zimbra
87
+ Zimbra::DateHelpers::Frequency.find(frequency).zimbra_name rescue frequency
88
+ end
89
+
90
+ def until_date=(val)
91
+ @until_date = Time.parse(val) rescue val
92
+ end
93
+
94
+ def by_set_position=(val)
95
+ if val == [0]
96
+ @by_set_position = nil
97
+ else
98
+ @by_set_position = val
99
+ end
100
+ end
101
+ def by_day=(val)
102
+ @by_day = if val.is_a?(Array)
103
+ val.collect do |day_specification|
104
+ day_specification[:day] = Zimbra::DateHelpers::WeekDay.find(day_specification[:day]) rescue day_specification[:day]
105
+ day_specification
106
+ end
107
+ else
108
+ val
109
+ end
110
+ end
111
+
112
+ def to_hash(options = {})
113
+ hash = {
114
+ :frequency => frequency ? frequency.to_sym : nil,
115
+ :interval => interval,
116
+ :by_month => by_month,
117
+ :by_month_day => by_month_day,
118
+ :count => count,
119
+ :until_date => until_date,
120
+ :by_set_position => by_set_position
121
+ }
122
+ hash[:by_day] = by_day.collect do |day_specification|
123
+ day_specification[:day] = day_specification[:day].to_sym if day_specification[:day]
124
+ day_specification
125
+ end if by_day
126
+ hash.reject! { |key, value| value.nil? }
127
+ hash.reject! { |key, value| options[:except].include?(key.to_sym) || options[:except].include?(key.to_s) } if options[:except]
128
+ hash.reject! { |key, value| !options[:only].include?(key.to_sym) && !options[:only].include?(key.to_s) } if options[:only]
129
+ hash
130
+ end
131
+
132
+ def create_xml(document)
133
+ document.add "rule" do |rule_element|
134
+ rule_element.set_attr "freq", frequency_to_zimbra
135
+
136
+ if until_date
137
+ rule_element.add "until" do |until_element|
138
+ until_element.set_attr "d", until_date.utc.strftime("%Y%m%dT%H%M%SZ")
139
+ end
140
+ end
141
+
142
+ rule_element.add "interval" do |interval_element|
143
+ interval_element.set_attr "ival", interval
144
+ end
145
+
146
+ if count && count > 0
147
+ rule_element.add "count" do |count_element|
148
+ count_element.set_attr "num", count
149
+ end
150
+ end
151
+
152
+ if by_day && by_day.count > 0
153
+ rule_element.add "byday" do |by_day_element|
154
+ by_day.each do |day_spec|
155
+ by_day_element.add "wkday" do |wkday_element|
156
+ wkday_element.set_attr "day", day_spec[:day].zimbra_name
157
+ wkday_element.set_attr "ordwk", day_spec[:week_number] if day_spec.has_key?(:week_number)
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ if by_month && by_month.count > 0
164
+ rule_element.add "bymonth" do |by_month_element|
165
+ by_month_element.set_attr "molist", by_month.join(',')
166
+ end
167
+ end
168
+
169
+ if by_month_day && by_month_day.count > 0
170
+ rule_element.add "bymonthday" do |by_month_day_element|
171
+ by_month_day_element.set_attr "modaylist", by_month_day.join(',')
172
+ end
173
+ end
174
+
175
+ if by_set_position
176
+ rule_element.add "bysetpos" do |bysetpos_element|
177
+ bysetpos_element.set_attr "poslist", by_set_position.join(',')
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,91 @@
1
+ module Zimbra
2
+ class Appointment
3
+ class Reply
4
+ ATTRS = [
5
+ :sequence_number, :date, :email_address, :participation_status, :sent_by, :recurrence_range_type, :recurrence_id, :timezone, :recurrence_id_utc
6
+ ] unless const_defined?(:ATTRS)
7
+
8
+ attr_accessor *ATTRS
9
+
10
+ class << self
11
+ def new_from_zimbra_attributes(zimbra_attributes)
12
+ new(parse_zimbra_attributes(zimbra_attributes))
13
+ end
14
+
15
+ def parse_zimbra_attributes(zimbra_attributes)
16
+ zimbra_attributes = Zimbra::Hash.symbolize_keys(zimbra_attributes.dup, true)
17
+
18
+ {
19
+ :sequence_number => zimbra_attributes[:seq],
20
+ :date => zimbra_attributes[:d],
21
+ :email_address => zimbra_attributes[:at],
22
+ :participation_status => zimbra_attributes[:ptst],
23
+ :sent_by => zimbra_attributes[:sentBy],
24
+ :recurrence_range_type => zimbra_attributes[:rangeType],
25
+ :recurrence_id => zimbra_attributes[:recurId],
26
+ :timezone => zimbra_attributes[:tz],
27
+ :recurrence_id_utc => zimbra_attributes[:ridZ]
28
+ }
29
+ end
30
+ end
31
+
32
+ def initialize(args = {})
33
+ self.attributes = args
34
+ end
35
+
36
+ # take attributes by the xml name or our more descriptive name
37
+ def attributes=(args = {})
38
+ ATTRS.each do |attr_name|
39
+ if args.has_key?(attr_name)
40
+ self.send(:"#{attr_name}=", args[attr_name])
41
+ elsif args.has_key?(attr_name.to_s)
42
+ self.send(:"#{attr_name}=", args[attr_name.to_s])
43
+ end
44
+ end
45
+ end
46
+
47
+ def participation_status=(val)
48
+ @participation_status = parse_participation_status(val)
49
+ end
50
+
51
+ def date=(val)
52
+ if val.is_a?(Integer)
53
+ @date = parse_date_in_seconds(val)
54
+ else
55
+ @date = val
56
+ end
57
+ end
58
+
59
+ def to_hash(options = {})
60
+ hash = ATTRS.inject({}) do |hash, attr_name|
61
+ hash[attr_name] = self.send(attr_name)
62
+ hash
63
+ end
64
+ hash.reject! { |key, value| options[:except].include?(key.to_sym) || options[:except].include?(key.to_s) } if options[:except]
65
+ hash.reject! { |key, value| !options[:only].include?(key.to_sym) && !options[:only].include?(key.to_s) } if options[:only]
66
+ hash
67
+ end
68
+
69
+ private
70
+
71
+ def parse_participation_status(status)
72
+ possible_values = {
73
+ 'NE' => :needs_action,
74
+ 'AC' => :accept,
75
+ 'TE' => :tentative,
76
+ 'DE' => :declined,
77
+ 'DG' => :delegated,
78
+ 'CO' => :completed,
79
+ 'IN' => :in_process,
80
+ 'WE' => :waiting,
81
+ 'DF' => :deferred
82
+ }
83
+ possible_values[status] || status
84
+ end
85
+
86
+ def parse_date_in_seconds(seconds)
87
+ Time.at(seconds / 1000)
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,46 @@
1
+ module Zimbra
2
+ class Auth
3
+ def self.login(username, password)
4
+ AuthService.login(username, password)
5
+ end
6
+ end
7
+
8
+ class AuthService < Handsoap::Service
9
+ include HandsoapErrors
10
+ include Zimbra::HandsoapNamespaces
11
+ extend HandsoapUriOverrides
12
+
13
+ def on_create_document(doc)
14
+ request_namespaces(doc)
15
+ end
16
+ def on_response_document(doc)
17
+ response_namespaces(doc)
18
+ end
19
+
20
+ def login(username, password)
21
+ xml = invoke('n2:AuthRequest') do |message|
22
+ Builder.auth(message, username, password)
23
+ end
24
+ [Parser.auth_token(xml), Parser.session_lifetime(xml)]
25
+ end
26
+
27
+ class Builder
28
+ class << self
29
+ def auth(message, username, password)
30
+ message.add 'name', username
31
+ message.add 'password', password
32
+ end
33
+ end
34
+ end
35
+ class Parser
36
+ class << self
37
+ def auth_token(response)
38
+ (response/'//n2:authToken').to_s
39
+ end
40
+ def session_lifetime(response)
41
+ (response/'//n2:lifetime').to_s
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,217 @@
1
+ module Zimbra
2
+
3
+ # Doc Placeholder
4
+ class Base
5
+ NAMESPACES = {
6
+ 'Domain' => 'domain',
7
+ 'Account' => 'account',
8
+ 'DistributionList' => 'dl'
9
+ }
10
+
11
+ class << self
12
+ def class_name
13
+ name.gsub(/Zimbra::/, '')
14
+ end
15
+
16
+ def all
17
+ BaseService.all(class_name)
18
+ end
19
+
20
+ def find_by_id(id)
21
+ BaseService.get_by_id(id, class_name)
22
+ end
23
+
24
+ def find_by_name(name)
25
+ BaseService.get_by_name(name, class_name)
26
+ end
27
+
28
+ def create(name, attrs = {})
29
+ BaseService.create(name, attrs, class_name)
30
+ end
31
+
32
+ end
33
+
34
+ attr_accessor :id, :name, :zimbra_attrs
35
+
36
+ def initialize(id, name, zimbra_attrs = {}, node = nil)
37
+ self.id = id
38
+ self.name = name
39
+ self.zimbra_attrs = zimbra_attrs
40
+ end
41
+
42
+ def acls
43
+ @acls ||= Zimbra::Directory.get_grants(self)
44
+ end
45
+
46
+ def delete
47
+ BaseService.delete(id, self.class.class_name)
48
+ end
49
+
50
+ def modify(attrs = {})
51
+ rename(attrs.delete('name')) if attrs['name']
52
+ BaseService.modify(id, attrs, self.class.class_name)
53
+ end
54
+
55
+ # Zimbra only allows renaming domains directly through LDAP
56
+ def rename(newname)
57
+ fail Zimbra::HandsoapErrors::NotImplemented.new('Rename domain only via LDAP') if self.is_a?(Zimbra::Domain)
58
+ BaseService.rename(id, newname, self.class.class_name)
59
+ end
60
+
61
+ def zimbra_type
62
+ Zimbra::Directory::TARGET_TYPES_MAPPING[self.class]
63
+ end
64
+
65
+ end
66
+
67
+ # Doc Placeholder
68
+ class BaseService < HandsoapService
69
+ def all(class_name)
70
+ request_name = "n2:GetAll#{class_name}sRequest"
71
+ xml = invoke(request_name)
72
+ Parser.get_all_response(class_name, xml)
73
+ end
74
+
75
+ def delete(id, class_name)
76
+ request_name = "n2:Delete#{class_name}Request"
77
+ xml = invoke(request_name) do |message|
78
+ Builder.delete(message, id)
79
+ end
80
+ true
81
+ end
82
+
83
+ def create(name, attributes = {}, class_name)
84
+ request_name = "n2:Create#{class_name}Request"
85
+ xml = invoke(request_name) do |message|
86
+ Builder.create(message, name, attributes)
87
+ end
88
+ namespace = Zimbra::Base::NAMESPACES[class_name]
89
+ Parser.response(class_name, xml/"//n2:#{namespace}")
90
+ end
91
+
92
+ def get_by_id(id, class_name)
93
+ request_name = "n2:Get#{class_name}Request"
94
+ xml = invoke(request_name) do |message|
95
+ Builder.get_by_id(message, id, class_name)
96
+ end
97
+ return nil if soap_fault_not_found?
98
+ namespace = Zimbra::Base::NAMESPACES[class_name]
99
+ Parser.response(class_name, xml/"//n2:#{namespace}")
100
+ end
101
+
102
+ def get_by_name(name, class_name)
103
+ request_name = "n2:Get#{class_name}Request"
104
+ xml = invoke(request_name) do |message|
105
+ Builder.get_by_name(message, name, class_name)
106
+ end
107
+ return nil if soap_fault_not_found?
108
+ namespace = Zimbra::Base::NAMESPACES[class_name]
109
+ Parser.response(class_name, xml/"//n2:#{namespace}")
110
+ end
111
+
112
+ def modify(id, attributes = {}, class_name)
113
+ request_name = "n2:Modify#{class_name}Request"
114
+ xml = invoke(request_name) do |message|
115
+ Builder.modify(message, id, attributes)
116
+ end
117
+ namespace = Zimbra::Base::NAMESPACES[class_name]
118
+ Parser.response(class_name, xml/"//n2:#{namespace}")
119
+ end
120
+
121
+ def rename(id, newname, class_name)
122
+ request_name = "n2:Rename#{class_name}Request"
123
+ xml = invoke(request_name) do |message|
124
+ Builder.rename(message, id, newname)
125
+ end
126
+ namespace = Zimbra::Base::NAMESPACES[class_name]
127
+ Parser.response(class_name, xml/"//n2:#{namespace}")
128
+ end
129
+
130
+ # Doc Placeholder
131
+ class Builder
132
+ class << self
133
+
134
+ def create(message, name, attributes = {})
135
+ message.add 'name', name
136
+ attributes.each do |k,v|
137
+ A.inject(message, k, v)
138
+ end
139
+ end
140
+
141
+ def delete(message, id)
142
+ message.set_attr 'id', id
143
+ end
144
+
145
+ def get_by_id(message, id, class_name)
146
+ namespace = Zimbra::Base::NAMESPACES[class_name]
147
+ message.add namespace, id do |c|
148
+ c.set_attr 'by', 'id'
149
+ end
150
+ end
151
+
152
+ def get_by_name(message, name, class_name)
153
+ namespace = Zimbra::Base::NAMESPACES[class_name]
154
+ message.add namespace, name do |c|
155
+ c.set_attr 'by', 'name'
156
+ end
157
+ end
158
+
159
+ def modify(message, id, attributes)
160
+ message.add 'id', id
161
+ modify_attributes(message, attributes)
162
+ end
163
+
164
+ def modify_attributes(message, attributes = {})
165
+ attributes.each do |k,v|
166
+ A.inject(message, k, v)
167
+ end
168
+ end
169
+
170
+ def rename(message, id, newname)
171
+ message.set_attr 'id', id
172
+ message.set_attr 'newName', newname
173
+ end
174
+
175
+ end
176
+ end
177
+
178
+ # Doc Placeholder
179
+ class Parser
180
+ class << self
181
+ def get_all_response(class_name, response)
182
+ namespace = Zimbra::Base::NAMESPACES[class_name]
183
+ (response/"//n2:#{namespace}").map do |node|
184
+ response(class_name, node, false)
185
+ end
186
+ end
187
+
188
+ def response(class_name, node, full = true)
189
+ attrs = full ? get_attributes(node) : {}
190
+ id = (node/'@id').to_s
191
+ name = (node/'@name').to_s
192
+
193
+ object = Object.const_get "Zimbra::#{class_name}"
194
+ object.new(id, name, attrs, node)
195
+ end
196
+
197
+ # This method run over the children of the node
198
+ # and for each one gets the value of the n attribute
199
+ # "<a n=\"zimbraMailAlias\">restringida@zbox.cl</a>"
200
+ # would be zimbraMailAlias
201
+ def get_attributes_names(node)
202
+ (node/'n2:a').map { |e| (e/'@n').to_s }.uniq
203
+ end
204
+
205
+ def get_attributes(node)
206
+ attr_hash = {}
207
+ attributes = get_attributes_names node
208
+ attributes.each do |attr|
209
+ attr_hash[attr] = Zimbra::A.read node, attr
210
+ end
211
+ attr_hash
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ end