zimbra-soap-api 0.0.7.9

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 (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