sfdcvp 0.0.1

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 (89) hide show
  1. checksums.yaml +15 -0
  2. data/Changelog.txt +1004 -0
  3. data/README.md +201 -0
  4. data/TODO +17 -0
  5. data/lib/ews/calendar_accessors.rb +34 -0
  6. data/lib/ews/connection.rb +126 -0
  7. data/lib/ews/connection_helper.rb +35 -0
  8. data/lib/ews/convert_accessors.rb +56 -0
  9. data/lib/ews/errors.rb +56 -0
  10. data/lib/ews/ews_client.rb +101 -0
  11. data/lib/ews/exceptions/exceptions.rb +61 -0
  12. data/lib/ews/folder_accessors.rb +264 -0
  13. data/lib/ews/impersonation.rb +30 -0
  14. data/lib/ews/item_accessors.rb +231 -0
  15. data/lib/ews/mailbox_accessors.rb +92 -0
  16. data/lib/ews/message_accessors.rb +93 -0
  17. data/lib/ews/push_subscription_accessors.rb +33 -0
  18. data/lib/ews/room_accessors.rb +48 -0
  19. data/lib/ews/roomlist_accessors.rb +47 -0
  20. data/lib/ews/soap.rb +64 -0
  21. data/lib/ews/soap/builders/ews_builder.rb +1361 -0
  22. data/lib/ews/soap/ews_response.rb +84 -0
  23. data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
  24. data/lib/ews/soap/ews_soap_free_busy_response.rb +119 -0
  25. data/lib/ews/soap/ews_soap_response.rb +103 -0
  26. data/lib/ews/soap/ews_soap_room_response.rb +53 -0
  27. data/lib/ews/soap/ews_soap_roomlist_response.rb +54 -0
  28. data/lib/ews/soap/exchange_availability.rb +61 -0
  29. data/lib/ews/soap/exchange_data_services.rb +780 -0
  30. data/lib/ews/soap/exchange_notification.rb +146 -0
  31. data/lib/ews/soap/exchange_synchronization.rb +93 -0
  32. data/lib/ews/soap/exchange_time_zones.rb +56 -0
  33. data/lib/ews/soap/exchange_user_configuration.rb +33 -0
  34. data/lib/ews/soap/exchange_web_service.rb +264 -0
  35. data/lib/ews/soap/parsers/ews_parser.rb +43 -0
  36. data/lib/ews/soap/parsers/ews_sax_document.rb +70 -0
  37. data/lib/ews/soap/response_message.rb +80 -0
  38. data/lib/ews/soap/responses/create_attachment_response_message.rb +47 -0
  39. data/lib/ews/soap/responses/create_item_response_message.rb +25 -0
  40. data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
  41. data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
  42. data/lib/ews/soap/responses/send_notification_response_message.rb +59 -0
  43. data/lib/ews/soap/responses/subscribe_response_message.rb +35 -0
  44. data/lib/ews/soap/responses/sync_folder_hierarchy_response_message.rb +36 -0
  45. data/lib/ews/soap/responses/sync_folder_items_response_message.rb +36 -0
  46. data/lib/ews/templates/calendar_item.rb +78 -0
  47. data/lib/ews/templates/forward_item.rb +24 -0
  48. data/lib/ews/templates/message.rb +73 -0
  49. data/lib/ews/templates/reply_to_item.rb +25 -0
  50. data/lib/ews/templates/task.rb +74 -0
  51. data/lib/ews/types.rb +194 -0
  52. data/lib/ews/types/attachment.rb +77 -0
  53. data/lib/ews/types/attendee.rb +27 -0
  54. data/lib/ews/types/calendar_folder.rb +50 -0
  55. data/lib/ews/types/calendar_item.rb +129 -0
  56. data/lib/ews/types/contact.rb +7 -0
  57. data/lib/ews/types/contacts_folder.rb +8 -0
  58. data/lib/ews/types/copied_event.rb +51 -0
  59. data/lib/ews/types/created_event.rb +24 -0
  60. data/lib/ews/types/deleted_event.rb +24 -0
  61. data/lib/ews/types/distribution_list.rb +7 -0
  62. data/lib/ews/types/event.rb +62 -0
  63. data/lib/ews/types/export_items_response_message.rb +52 -0
  64. data/lib/ews/types/file_attachment.rb +65 -0
  65. data/lib/ews/types/folder.rb +60 -0
  66. data/lib/ews/types/free_busy_changed_event.rb +24 -0
  67. data/lib/ews/types/generic_folder.rb +420 -0
  68. data/lib/ews/types/item.rb +442 -0
  69. data/lib/ews/types/item_attachment.rb +84 -0
  70. data/lib/ews/types/item_field_uri_map.rb +224 -0
  71. data/lib/ews/types/mailbox_user.rb +156 -0
  72. data/lib/ews/types/meeting_cancellation.rb +7 -0
  73. data/lib/ews/types/meeting_message.rb +7 -0
  74. data/lib/ews/types/meeting_request.rb +7 -0
  75. data/lib/ews/types/meeting_response.rb +7 -0
  76. data/lib/ews/types/message.rb +7 -0
  77. data/lib/ews/types/modified_event.rb +48 -0
  78. data/lib/ews/types/moved_event.rb +51 -0
  79. data/lib/ews/types/new_mail_event.rb +24 -0
  80. data/lib/ews/types/out_of_office.rb +147 -0
  81. data/lib/ews/types/search_folder.rb +8 -0
  82. data/lib/ews/types/status_event.rb +39 -0
  83. data/lib/ews/types/task.rb +37 -0
  84. data/lib/ews/types/tasks_folder.rb +27 -0
  85. data/lib/sfdcvp.rb +109 -0
  86. data/lib/viewpoint/logging.rb +27 -0
  87. data/lib/viewpoint/logging/config.rb +24 -0
  88. data/lib/viewpoint/string_utils.rb +76 -0
  89. metadata +190 -0
@@ -0,0 +1,52 @@
1
+ module Viewpoint::EWS::Types
2
+
3
+ class ExportItemsResponseMessage
4
+ include Viewpoint::EWS
5
+ include Viewpoint::EWS::Types
6
+ include Viewpoint::EWS::Types::Item
7
+
8
+ BULK_KEY_PATHS = {
9
+ :id => [:item_id, :attribs, :id],
10
+ :change_key => [:item_id, :attribs, :change_key],
11
+ :data => [:data, :text]
12
+ }
13
+
14
+ BULK_KEY_TYPES = { }
15
+
16
+ BULK_KEY_ALIAS = { }
17
+
18
+ def initialize(ews, bulk_item)
19
+ super(ews, bulk_item)
20
+ @item = bulk_item
21
+ @ews = ews
22
+ end
23
+
24
+ def id
25
+ @item[:item_id][:attribs][:id]
26
+ end
27
+
28
+ def change_key
29
+ @item[:item_id][:attribs][:change_key]
30
+ end
31
+
32
+ def data
33
+ @item[:data][:text]
34
+ end
35
+
36
+
37
+ private
38
+
39
+ def key_paths
40
+ @key_paths ||= BULK_KEY_PATHS
41
+ end
42
+
43
+ def key_types
44
+ @key_types ||= BULK_KEY_TYPES
45
+ end
46
+
47
+ def key_alias
48
+ @key_alias ||= BULK_KEY_ALIAS
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,65 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::EWS::Types
20
+ class FileAttachment < Attachment
21
+
22
+ FILE_ATTACH_KEY_PATHS = {
23
+ :is_contact_photo? => [:is_contact_photo, :text],
24
+ :content => [:content, :text],
25
+ }
26
+
27
+ FILE_ATTACH_KEY_TYPES = {
28
+ is_contact_photo?: ->(str){str.downcase == 'true'},
29
+ }
30
+
31
+ FILE_ATTACH_KEY_ALIAS = {
32
+ :file_name => :name,
33
+ }
34
+
35
+ def get_all_properties!
36
+ resp = ews.get_attachment attachment_ids: [self.id]
37
+ @ews_item.merge!(parse_response(resp))
38
+ end
39
+
40
+ private
41
+
42
+
43
+ def key_paths
44
+ super.merge(FILE_ATTACH_KEY_PATHS)
45
+ end
46
+
47
+ def key_types
48
+ super.merge(FILE_ATTACH_KEY_TYPES)
49
+ end
50
+
51
+ def key_alias
52
+ super.merge(FILE_ATTACH_KEY_ALIAS)
53
+ end
54
+
55
+ def parse_response(resp)
56
+ if(resp.status == 'Success')
57
+ resp.response_message[:elems][:attachments][:elems][0][:file_attachment][:elems].inject(&:merge)
58
+ else
59
+ raise EwsError, "Could not retrieve #{self.class}. #{resp.code}: #{resp.message}"
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+
@@ -0,0 +1,60 @@
1
+ module Viewpoint::EWS::Types
2
+ class Folder
3
+ include Viewpoint::EWS
4
+ include Viewpoint::EWS::Types
5
+ include Viewpoint::EWS::Types::GenericFolder
6
+
7
+ FOLDER_KEY_PATHS = {
8
+ :unread_count => [:unread_count, :text],
9
+ }
10
+ FOLDER_KEY_TYPES = {
11
+ :unread_count => ->(str){str.to_i},
12
+ }
13
+ FOLDER_KEY_ALIAS = {}
14
+
15
+ alias :messages :items
16
+
17
+ def unread_messages
18
+ self.items read_unread_restriction
19
+ end
20
+
21
+ def read_messages
22
+ self.items read_unread_restriction(true)
23
+ end
24
+
25
+ def messages_with_attachments
26
+ opts = {:restriction =>
27
+ {:is_equal_to => [
28
+ {:field_uRI => {:field_uRI=>'item:HasAttachments'}},
29
+ {:field_uRI_or_constant => {:constant => {:value=> true}}}
30
+ ]}
31
+ }
32
+ self.items opts
33
+ end
34
+
35
+ private
36
+
37
+
38
+ def read_unread_restriction(read = false)
39
+ {:restriction =>
40
+ {:is_equal_to => [
41
+ {:field_uRI => {:field_uRI=>'message:IsRead'}},
42
+ {:field_uRI_or_constant => {:constant => {:value=> read}}}
43
+ ]}
44
+ }
45
+ end
46
+
47
+ def key_paths
48
+ @key_paths ||= super.merge(FOLDER_KEY_PATHS)
49
+ end
50
+
51
+ def key_types
52
+ @key_types ||= super.merge(FOLDER_KEY_TYPES)
53
+ end
54
+
55
+ def key_alias
56
+ @key_alias ||= super.merge(FOLDER_KEY_ALIAS)
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,24 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::EWS::Types
20
+
21
+ class FreeBusyChangedEvent < Event
22
+
23
+ end
24
+ end
@@ -0,0 +1,420 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ require 'ews/item_accessors'
20
+
21
+ module Viewpoint::EWS::Types
22
+ module GenericFolder
23
+ include Viewpoint::EWS
24
+ include Viewpoint::EWS::Types
25
+ include Viewpoint::EWS::ItemAccessors
26
+ include Viewpoint::StringUtils
27
+
28
+ GFOLDER_KEY_PATHS = {
29
+ :folder_id => [:folder_id, :attribs],
30
+ :id => [:folder_id, :attribs, :id],
31
+ :change_key => [:folder_id, :attribs, :change_key],
32
+ :parent_folder_id => [:parent_folder_id, :attribs, :id],
33
+ :parent_folder_change_key => [:parent_folder_id, :attribs, :change_key],
34
+ :folder_class => [:folder_class, :text],
35
+ :total_count => [:total_count, :text],
36
+ :child_folder_count => [:child_folder_count, :text],
37
+ :display_name => [:display_name, :text],
38
+ }
39
+
40
+ GFOLDER_KEY_TYPES = {
41
+ :total_count => ->(str){str.to_i},
42
+ :child_folder_count => ->(str){str.to_i},
43
+ }
44
+
45
+ GFOLDER_KEY_ALIAS = {
46
+ :name => :display_name,
47
+ :ckey => :change_key,
48
+ }
49
+
50
+ attr_accessor :subscription_id, :watermark, :sync_state
51
+
52
+ # @param [SOAP::ExchangeWebService] ews the EWS reference
53
+ # @param [Hash] ews_item the EWS parsed response document
54
+ def initialize(ews, ews_item)
55
+ super
56
+ simplify!
57
+ @sync_state = nil
58
+ @synced = false
59
+ end
60
+
61
+ def delete!
62
+ opts = {
63
+ :folder_ids => [:id => id],
64
+ :delete_type => 'HardDelete'
65
+ }
66
+ resp = @ews.delete_folder(opts)
67
+ if resp.success?
68
+ true
69
+ else
70
+ raise EwsError, "Could not delete folder. #{resp.code}: #{resp.message}"
71
+ end
72
+ end
73
+
74
+ def items(opts = {})
75
+ args = items_args(opts.clone)
76
+ obj = OpenStruct.new(opts: args, restriction: {})
77
+ yield obj if block_given?
78
+ merge_restrictions! obj
79
+ resp = ews.find_item(args)
80
+ items_parser resp
81
+ end
82
+
83
+ # Fetch items since a give DateTime
84
+ # @param [DateTime] date_time the time to fetch Items since.
85
+ def items_since(date_time, opts = {})
86
+ opts = opts.clone
87
+ unless date_time.kind_of?(Date)
88
+ raise EwsBadArgumentError, "First argument must be a Date or DateTime"
89
+ end
90
+ restr = {:restriction =>
91
+ {:is_greater_than_or_equal_to =>
92
+ [{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
93
+ {:field_uRI_or_constant =>{:constant => {:value=>date_time.to_datetime}}}]
94
+ }}
95
+ items(opts.merge(restr))
96
+ end
97
+
98
+ # Fetch only items from today (since midnight)
99
+ def todays_items(opts = {})
100
+ items_since(Date.today)
101
+ end
102
+
103
+ # Fetch items between a given time period
104
+ # @param [DateTime] start_date the time to start fetching Items from
105
+ # @param [DateTime] end_date the time to stop fetching Items from
106
+ def items_between(start_date, end_date, opts={})
107
+ items do |obj|
108
+ obj.restriction = { :and =>
109
+ [
110
+ {:is_greater_than_or_equal_to =>
111
+ [
112
+ {:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
113
+ {:field_uRI_or_constant=>{:constant => {:value =>start_date}}}
114
+ ]
115
+ },
116
+ {:is_less_than_or_equal_to =>
117
+ [
118
+ {:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
119
+ {:field_uRI_or_constant=>{:constant => {:value =>end_date}}}
120
+ ]
121
+ }
122
+ ]
123
+ }
124
+ end
125
+ end
126
+
127
+ # Search on the item subject
128
+ # @param [String] match_str A simple string paramater to match against the
129
+ # subject. The search ignores case and does not accept regexes... only strings.
130
+ # @param [String,nil] exclude_str A string to exclude from matches against
131
+ # the subject. This is optional.
132
+ def search_by_subject(match_str, exclude_str = nil)
133
+ items do |obj|
134
+ match = {:contains => {
135
+ :containment_mode => 'Substring',
136
+ :containment_comparison => 'IgnoreCase',
137
+ :field_uRI => {:field_uRI=>'item:Subject'},
138
+ :constant => {:value =>match_str}
139
+ }}
140
+ unless exclude_str.nil?
141
+ excl = {:not =>
142
+ {:contains => {
143
+ :containment_mode => 'Substring',
144
+ :containment_comparison => 'IgnoreCase',
145
+ :field_uRI => {:field_uRI=>'item:Subject'},
146
+ :constant => {:value =>exclude_str}
147
+ }}
148
+ }
149
+
150
+ match[:and] = [{:contains => match.delete(:contains)}, excl]
151
+ end
152
+ obj.restriction = match
153
+ end
154
+ end
155
+
156
+ def get_all_properties!
157
+ @ews_item = get_folder(:base_shape => 'AllProperties')
158
+ simplify!
159
+ end
160
+
161
+ def available_categories
162
+ opts = {
163
+ user_config_name: {
164
+ name: 'CategoryList',
165
+ distinguished_folder_id: {id: :calendar}
166
+ },
167
+ user_config_props: 'XmlData'
168
+ }
169
+ resp = ews.get_user_configuration(opts)
170
+ #txt = resp.response_message[:elems][:get_user_configuration_response_message][:elems][1][:user_configuration][:elems][1][:xml_data][:text]
171
+ #Base64.decode64 txt
172
+ end
173
+
174
+ # Syncronize Items in this folder. If this method is issued multiple
175
+ # times it will continue where the last sync completed.
176
+ # @param [Integer] sync_amount The number of items to synchronize per sync
177
+ # @param [Boolean] sync_all Whether to sync all the data by looping through.
178
+ # The default is to just sync the first set. You can manually loop through
179
+ # with multiple calls to #sync_items!
180
+ # @return [Hash] Returns a hash with keys for each change type that ocurred.
181
+ # Possible key values are:
182
+ # (:create/:udpate/:delete/:read_flag_change).
183
+ # For :deleted and :read_flag_change items a simple hash with :id and
184
+ # :change_key is returned.
185
+ # See: http://msdn.microsoft.com/en-us/library/aa565609.aspx
186
+ def sync_items!(sync_state = nil, sync_amount = 256, sync_all = false, opts = {})
187
+ item_shape = opts.has_key?(:item_shape) ? opts.delete(:item_shape) : {:base_shape => :default}
188
+ sync_state ||= @sync_state
189
+
190
+ resp = ews.sync_folder_items item_shape: item_shape,
191
+ sync_folder_id: self.folder_id, max_changes_returned: sync_amount, sync_state: sync_state
192
+ rmsg = resp.response_messages[0]
193
+
194
+ if rmsg.success?
195
+ @synced = rmsg.includes_last_item_in_range?
196
+ @sync_state = rmsg.sync_state
197
+ rhash = {}
198
+ rmsg.changes.each do |c|
199
+ ctype = c.keys.first
200
+ rhash[ctype] = [] unless rhash.has_key?(ctype)
201
+ if ctype == :delete || ctype == :read_flag_change
202
+ rhash[ctype] << c[ctype][:elems][0][:item_id][:attribs]
203
+ else
204
+ type = c[ctype][:elems][0].keys.first
205
+ item = class_by_name(type).new(ews, c[ctype][:elems][0][type])
206
+ rhash[ctype] << item
207
+ end
208
+ end
209
+ rhash
210
+ else
211
+ raise EwsError, "Could not synchronize: #{rmsg.code}: #{rmsg.message_text}"
212
+ end
213
+ end
214
+
215
+ def synced?
216
+ @synced
217
+ end
218
+
219
+ # Subscribe this folder to events. This method initiates an Exchange pull
220
+ # type subscription.
221
+ #
222
+ # @param event_types [Array] Which event types to subscribe to. By default
223
+ # we subscribe to all Exchange event types: :all, :copied, :created,
224
+ # :deleted, :modified, :moved, :new_mail, :free_busy_changed
225
+ # @param watermark [String] pass a watermark if you wish to start the
226
+ # subscription at a specific point.
227
+ # @param timeout [Fixnum] the time in minutes that the subscription can
228
+ # remain idle between calls to #get_events. default: 240 minutes
229
+ # @return [Boolean] Did the subscription happen successfully?
230
+ def subscribe(evtypes = [:all], watermark = nil, timeout = 240)
231
+ # Refresh the subscription if already subscribed
232
+ unsubscribe if subscribed?
233
+
234
+ event_types = normalize_event_names(evtypes)
235
+ folder = {id: self.id, change_key: self.change_key}
236
+ resp = ews.pull_subscribe_folder(folder, event_types, timeout, watermark)
237
+ rmsg = resp.response_messages.first
238
+ if rmsg.success?
239
+ @subscription_id = rmsg.subscription_id
240
+ @watermark = rmsg.watermark
241
+ true
242
+ else
243
+ raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
244
+ end
245
+ end
246
+
247
+ def push_subscribe(url, evtypes = [:all], watermark = nil, status_frequency = nil)
248
+ # Refresh the subscription if already subscribed
249
+ unsubscribe if subscribed?
250
+
251
+ event_types = normalize_event_names(evtypes)
252
+ folder = {id: self.id, change_key: self.change_key}
253
+ resp = ews.push_subscribe_folder(folder, event_types, url, status_frequency, watermark)
254
+ rmsg = resp.response_messages.first
255
+ if rmsg.success?
256
+ @subscription_id = rmsg.subscription_id
257
+ @watermark = rmsg.watermark
258
+ true
259
+ else
260
+ raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
261
+ end
262
+ end
263
+
264
+ # Check if there is a subscription for this folder.
265
+ # @return [Boolean] Are we subscribed to this folder?
266
+ def subscribed?
267
+ ( @subscription_id.nil? or @watermark.nil? )? false : true
268
+ end
269
+
270
+ # Unsubscribe this folder from further Exchange events.
271
+ # @return [Boolean] Did we unsubscribe successfully?
272
+ def unsubscribe
273
+ return true if @subscription_id.nil?
274
+
275
+ resp = ews.unsubscribe(@subscription_id)
276
+ rmsg = resp.response_messages.first
277
+ if rmsg.success?
278
+ @subscription_id, @watermark = nil, nil
279
+ true
280
+ else
281
+ raise EwsSubscriptionError, "Could not unsubscribe: #{rmsg.code}: #{rmsg.message_text}"
282
+ end
283
+ end
284
+
285
+ # Checks a subscribed folder for events
286
+ # @return [Array] An array of Event items
287
+ def get_events
288
+ begin
289
+ if subscribed?
290
+ resp = ews.get_events(@subscription_id, @watermark)
291
+ rmsg = resp.response_messages[0]
292
+ @watermark = rmsg.new_watermark
293
+ # @todo if parms[:more_events] # get more events
294
+ rmsg.events.collect{|ev|
295
+ type = ev.keys.first
296
+ class_by_name(type).new(ews, ev[type])
297
+ }
298
+ else
299
+ raise EwsSubscriptionError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
300
+ end
301
+ rescue EwsSubscriptionTimeout => e
302
+ @subscription_id, @watermark = nil, nil
303
+ raise e
304
+ end
305
+ end
306
+
307
+
308
+ private
309
+
310
+
311
+ def key_paths
312
+ @key_paths ||= super.merge(GFOLDER_KEY_PATHS)
313
+ end
314
+
315
+ def key_types
316
+ @key_types ||= super.merge(GFOLDER_KEY_TYPES)
317
+ end
318
+
319
+ def key_alias
320
+ @key_alias ||= super.merge(GFOLDER_KEY_ALIAS)
321
+ end
322
+
323
+ def simplify!
324
+ @ews_item = @ews_item[:elems].inject({}) do |o,i|
325
+ key = i.keys.first
326
+ if o.has_key?(key)
327
+ if o[key].is_a?(Array)
328
+ o[key] << i[key]
329
+ else
330
+ o[key] = [o.delete(key), i[key]]
331
+ end
332
+ else
333
+ o[key] = i[key]
334
+ end
335
+ o
336
+ end
337
+ end
338
+
339
+ # Get a specific folder by its ID.
340
+ # @param [Hash] opts Misc options to control request
341
+ # @option opts [String] :base_shape IdOnly/Default/AllProperties
342
+ # @raise [EwsError] raised when the backend SOAP method returns an error.
343
+ def get_folder(opts = {})
344
+ args = get_folder_args(opts)
345
+ resp = ews.get_folder(args)
346
+ get_folder_parser(resp)
347
+ end
348
+
349
+ # Build up the arguements for #get_folder
350
+ # @todo: should we really pass the ChangeKey or do we want the freshest obj?
351
+ def get_folder_args(opts)
352
+ opts[:base_shape] ||= 'Default'
353
+ default_args = {
354
+ :folder_ids => [{:id => self.id, :change_key => self.change_key}],
355
+ :folder_shape => {:base_shape => opts[:base_shape]}
356
+ }
357
+ default_args.merge(opts)
358
+ end
359
+
360
+ def get_folder_parser(resp)
361
+ if(resp.status == 'Success')
362
+ f = resp.response_message[:elems][:folders][:elems][0]
363
+ f.values.first
364
+ else
365
+ raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
366
+ end
367
+ end
368
+
369
+ def items_args(opts)
370
+ default_args = {
371
+ :parent_folder_ids => [{:id => self.id}],
372
+ :traversal => 'Shallow',
373
+ :item_shape => {:base_shape => 'Default'}
374
+ }.merge(opts)
375
+ end
376
+
377
+ def items_parser(resp)
378
+ rm = resp.response_messages[0]
379
+ if(rm.status == 'Success')
380
+ items = []
381
+ rm.root_folder.items.each do |i|
382
+ type = i.keys.first
383
+ items << class_by_name(type).new(ews, i[type], self)
384
+ end
385
+ items
386
+ else
387
+ raise EwsError, "Could not retrieve folder. #{rm.code}: #{rm.message_text}"
388
+ end
389
+ end
390
+
391
+ def merge_restrictions!(obj, merge_type = :and)
392
+ if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty?
393
+ obj.opts[:restriction] = {
394
+ merge_type => [
395
+ obj.opts.delete(:restriction),
396
+ obj.restriction
397
+ ]
398
+ }
399
+ elsif !obj.restriction.empty?
400
+ obj.opts[:restriction] = obj.restriction
401
+ end
402
+ end
403
+
404
+ def normalize_event_names(events)
405
+ if events.include?(:all)
406
+ events = [:copied, :created, :deleted, :modified, :moved, :new_mail, :free_busy_changed]
407
+ end
408
+
409
+ events.collect do |ev|
410
+ nev = ruby_case(ev)
411
+ if nev.end_with?('_event')
412
+ nev.to_sym
413
+ else
414
+ "#{nev}_event".to_sym
415
+ end
416
+ end
417
+ end
418
+
419
+ end
420
+ end