viewpoint_reloaded 1.0.0

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 +7 -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 +130 -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 +103 -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 +1266 -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 +79 -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 +130 -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 +418 -0
  68. data/lib/ews/types/item.rb +441 -0
  69. data/lib/ews/types/item_attachment.rb +84 -0
  70. data/lib/ews/types/item_field_uri_map.rb +208 -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 +41 -0
  84. data/lib/ews/types/tasks_folder.rb +27 -0
  85. data/lib/viewpoint.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 +192 -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,418 @@
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
+
249
+ event_types = normalize_event_names(evtypes)
250
+ folder = {id: self.id, change_key: self.change_key}
251
+ resp = ews.push_subscribe_folder(folder, event_types, url, status_frequency, watermark)
252
+ rmsg = resp.response_messages.first
253
+ if rmsg.success?
254
+ @subscription_id = rmsg.subscription_id
255
+ @watermark = rmsg.watermark
256
+ true
257
+ else
258
+ raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
259
+ end
260
+ end
261
+
262
+ # Check if there is a subscription for this folder.
263
+ # @return [Boolean] Are we subscribed to this folder?
264
+ def subscribed?
265
+ ( @subscription_id.nil? or @watermark.nil? )? false : true
266
+ end
267
+
268
+ # Unsubscribe this folder from further Exchange events.
269
+ # @return [Boolean] Did we unsubscribe successfully?
270
+ def unsubscribe
271
+ return true if @subscription_id.nil?
272
+
273
+ resp = ews.unsubscribe(@subscription_id)
274
+ rmsg = resp.response_messages.first
275
+ if rmsg.success?
276
+ @subscription_id, @watermark = nil, nil
277
+ true
278
+ else
279
+ raise EwsSubscriptionError, "Could not unsubscribe: #{rmsg.code}: #{rmsg.message_text}"
280
+ end
281
+ end
282
+
283
+ # Checks a subscribed folder for events
284
+ # @return [Array] An array of Event items
285
+ def get_events
286
+ begin
287
+ if subscribed?
288
+ resp = ews.get_events(@subscription_id, @watermark)
289
+ rmsg = resp.response_messages[0]
290
+ @watermark = rmsg.new_watermark
291
+ # @todo if parms[:more_events] # get more events
292
+ rmsg.events.collect{|ev|
293
+ type = ev.keys.first
294
+ class_by_name(type).new(ews, ev[type])
295
+ }
296
+ else
297
+ raise EwsSubscriptionError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
298
+ end
299
+ rescue EwsSubscriptionTimeout => e
300
+ @subscription_id, @watermark = nil, nil
301
+ raise e
302
+ end
303
+ end
304
+
305
+
306
+ private
307
+
308
+
309
+ def key_paths
310
+ @key_paths ||= super.merge(GFOLDER_KEY_PATHS)
311
+ end
312
+
313
+ def key_types
314
+ @key_types ||= super.merge(GFOLDER_KEY_TYPES)
315
+ end
316
+
317
+ def key_alias
318
+ @key_alias ||= super.merge(GFOLDER_KEY_ALIAS)
319
+ end
320
+
321
+ def simplify!
322
+ @ews_item = @ews_item[:elems].inject({}) do |o,i|
323
+ key = i.keys.first
324
+ if o.has_key?(key)
325
+ if o[key].is_a?(Array)
326
+ o[key] << i[key]
327
+ else
328
+ o[key] = [o.delete(key), i[key]]
329
+ end
330
+ else
331
+ o[key] = i[key]
332
+ end
333
+ o
334
+ end
335
+ end
336
+
337
+ # Get a specific folder by its ID.
338
+ # @param [Hash] opts Misc options to control request
339
+ # @option opts [String] :base_shape IdOnly/Default/AllProperties
340
+ # @raise [EwsError] raised when the backend SOAP method returns an error.
341
+ def get_folder(opts = {})
342
+ args = get_folder_args(opts)
343
+ resp = ews.get_folder(args)
344
+ get_folder_parser(resp)
345
+ end
346
+
347
+ # Build up the arguements for #get_folder
348
+ # @todo: should we really pass the ChangeKey or do we want the freshest obj?
349
+ def get_folder_args(opts)
350
+ opts[:base_shape] ||= 'Default'
351
+ default_args = {
352
+ :folder_ids => [{:id => self.id, :change_key => self.change_key}],
353
+ :folder_shape => {:base_shape => opts[:base_shape]}
354
+ }
355
+ default_args.merge(opts)
356
+ end
357
+
358
+ def get_folder_parser(resp)
359
+ if(resp.status == 'Success')
360
+ f = resp.response_message[:elems][:folders][:elems][0]
361
+ f.values.first
362
+ else
363
+ raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
364
+ end
365
+ end
366
+
367
+ def items_args(opts)
368
+ default_args = {
369
+ :parent_folder_ids => [{:id => self.id}],
370
+ :traversal => 'Shallow',
371
+ :item_shape => {:base_shape => 'Default'}
372
+ }.merge(opts)
373
+ end
374
+
375
+ def items_parser(resp)
376
+ rm = resp.response_messages[0]
377
+ if(rm.status == 'Success')
378
+ items = []
379
+ rm.root_folder.items.each do |i|
380
+ type = i.keys.first
381
+ items << class_by_name(type).new(ews, i[type], self)
382
+ end
383
+ items
384
+ else
385
+ raise EwsError, "Could not retrieve folder. #{rm.code}: #{rm.message_text}"
386
+ end
387
+ end
388
+
389
+ def merge_restrictions!(obj, merge_type = :and)
390
+ if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty?
391
+ obj.opts[:restriction] = {
392
+ merge_type => [
393
+ obj.opts.delete(:restriction),
394
+ obj.restriction
395
+ ]
396
+ }
397
+ elsif !obj.restriction.empty?
398
+ obj.opts[:restriction] = obj.restriction
399
+ end
400
+ end
401
+
402
+ def normalize_event_names(events)
403
+ if events.include?(:all)
404
+ events = [:copied, :created, :deleted, :modified, :moved, :new_mail, :free_busy_changed]
405
+ end
406
+
407
+ events.collect do |ev|
408
+ nev = ruby_case(ev)
409
+ if nev.end_with?('_event')
410
+ nev.to_sym
411
+ else
412
+ "#{nev}_event".to_sym
413
+ end
414
+ end
415
+ end
416
+
417
+ end
418
+ end