viewpoint 0.1.27 → 1.0.0.beta.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 (93) hide show
  1. data/README.md +196 -0
  2. data/lib/ews/calendar_accessors.rb +34 -0
  3. data/lib/ews/connection.rb +117 -0
  4. data/lib/ews/connection_helper.rb +35 -0
  5. data/lib/ews/ews_client.rb +71 -0
  6. data/lib/ews/exceptions/exceptions.rb +59 -0
  7. data/lib/ews/folder_accessors.rb +199 -0
  8. data/lib/ews/item_accessors.rb +157 -0
  9. data/lib/ews/mailbox_accessors.rb +87 -0
  10. data/lib/ews/message_accessors.rb +86 -0
  11. data/lib/ews/push_subscription_accessors.rb +33 -0
  12. data/lib/ews/soap.rb +63 -0
  13. data/lib/ews/soap/builders/ews_builder.rb +1011 -0
  14. data/lib/ews/soap/ews_response.rb +83 -0
  15. data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
  16. data/lib/ews/soap/ews_soap_free_busy_response.rb +109 -0
  17. data/lib/ews/soap/ews_soap_response.rb +103 -0
  18. data/lib/ews/soap/exchange_availability.rb +61 -0
  19. data/lib/ews/soap/exchange_data_services.rb +742 -0
  20. data/lib/ews/soap/exchange_notification.rb +146 -0
  21. data/lib/ews/soap/exchange_user_configuration.rb +33 -0
  22. data/lib/ews/soap/exchange_web_service.rb +294 -0
  23. data/lib/{model/attendee.rb → ews/soap/parsers/ews_parser.rb} +20 -14
  24. data/lib/ews/soap/parsers/ews_sax_document.rb +66 -0
  25. data/lib/ews/soap/response_message.rb +78 -0
  26. data/lib/ews/soap/responses/create_attachment_response_message.rb +46 -0
  27. data/lib/{model/meeting_message.rb → ews/soap/responses/create_item_response_message.rb} +7 -10
  28. data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
  29. data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
  30. data/lib/ews/soap/responses/send_notification_response_message.rb +58 -0
  31. data/lib/{model/attachment.rb → ews/soap/responses/subscribe_response_message.rb} +17 -13
  32. data/lib/ews/templates/forward_item.rb +24 -0
  33. data/lib/ews/templates/message.rb +66 -0
  34. data/lib/ews/templates/reply_to_item.rb +25 -0
  35. data/lib/ews/types.rb +146 -0
  36. data/lib/ews/types/attachment.rb +77 -0
  37. data/lib/{model/meeting_cancellation.rb → ews/types/attendee.rb} +9 -8
  38. data/lib/ews/types/calendar_folder.rb +8 -0
  39. data/lib/ews/types/calendar_item.rb +37 -0
  40. data/lib/ews/types/contact.rb +7 -0
  41. data/lib/ews/types/contacts_folder.rb +8 -0
  42. data/lib/ews/types/copied_event.rb +51 -0
  43. data/lib/{soap/handsoap/builder.rb → ews/types/created_event.rb} +5 -2
  44. data/lib/{model/meeting_response.rb → ews/types/deleted_event.rb} +6 -6
  45. data/lib/ews/types/distribution_list.rb +7 -0
  46. data/lib/ews/types/event.rb +62 -0
  47. data/lib/ews/types/file_attachment.rb +65 -0
  48. data/lib/ews/types/folder.rb +60 -0
  49. data/lib/{model/distribution_list.rb → ews/types/free_busy_changed_event.rb} +6 -6
  50. data/lib/ews/types/generic_folder.rb +352 -0
  51. data/lib/ews/types/item.rb +381 -0
  52. data/lib/ews/types/item_attachment.rb +46 -0
  53. data/lib/{model → ews/types}/item_field_uri_map.rb +2 -2
  54. data/lib/ews/types/mailbox_user.rb +156 -0
  55. data/lib/ews/types/meeting_cancellation.rb +7 -0
  56. data/lib/ews/types/meeting_message.rb +7 -0
  57. data/lib/ews/types/meeting_request.rb +7 -0
  58. data/lib/ews/types/meeting_response.rb +7 -0
  59. data/lib/ews/types/message.rb +7 -0
  60. data/lib/ews/types/modified_event.rb +48 -0
  61. data/lib/{model/item_attachment.rb → ews/types/moved_event.rb} +33 -15
  62. data/lib/ews/types/new_mail_event.rb +24 -0
  63. data/lib/ews/types/out_of_office.rb +147 -0
  64. data/lib/ews/types/search_folder.rb +8 -0
  65. data/lib/ews/types/status_event.rb +39 -0
  66. data/lib/ews/types/task.rb +7 -0
  67. data/lib/ews/types/tasks_folder.rb +8 -0
  68. data/lib/viewpoint.rb +82 -106
  69. metadata +99 -67
  70. data/README +0 -114
  71. data/lib/exceptions/exceptions.rb +0 -46
  72. data/lib/model/calendar_folder.rb +0 -67
  73. data/lib/model/calendar_item.rb +0 -267
  74. data/lib/model/contact.rb +0 -238
  75. data/lib/model/contacts_folder.rb +0 -46
  76. data/lib/model/event.rb +0 -116
  77. data/lib/model/file_attachment.rb +0 -53
  78. data/lib/model/folder.rb +0 -47
  79. data/lib/model/generic_folder.rb +0 -471
  80. data/lib/model/item.rb +0 -313
  81. data/lib/model/mailbox_user.rb +0 -146
  82. data/lib/model/meeting_request.rb +0 -39
  83. data/lib/model/message.rb +0 -142
  84. data/lib/model/model.rb +0 -269
  85. data/lib/model/search_folder.rb +0 -48
  86. data/lib/model/task.rb +0 -121
  87. data/lib/model/tasks_folder.rb +0 -44
  88. data/lib/soap/handsoap/builders/ews_build_helpers.rb +0 -383
  89. data/lib/soap/handsoap/builders/ews_builder.rb +0 -146
  90. data/lib/soap/handsoap/ews_service.rb +0 -813
  91. data/lib/soap/handsoap/parser.rb +0 -104
  92. data/lib/soap/handsoap/parsers/ews_parser.rb +0 -246
  93. data/lib/soap/soap_provider.rb +0 -64
@@ -0,0 +1,7 @@
1
+ module Viewpoint::EWS::Types
2
+ class Contact
3
+ include Viewpoint::EWS
4
+ include Viewpoint::EWS::Types
5
+ include Viewpoint::EWS::Types::Item
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Viewpoint::EWS::Types
2
+ class ContactsFolder
3
+ include Viewpoint::EWS
4
+ include Viewpoint::EWS::Types
5
+ include Viewpoint::EWS::Types::GenericFolder
6
+
7
+ end
8
+ end
@@ -0,0 +1,51 @@
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 CopiedEvent < Event
22
+
23
+ COPIED_EVENT_KEY_PATHS = {
24
+ :old_item_id => [:old_item_id, :attribs],
25
+ :old_folder_id => [:old_folder_id, :attribs],
26
+ :old_parent_folder_id => [:old_parent_folder_id, :attribs],
27
+ }
28
+
29
+ COPIED_EVENT_KEY_TYPES = {
30
+ }
31
+
32
+ COPIED_EVENT_KEY_ALIAS = { }
33
+
34
+
35
+ private
36
+
37
+
38
+ def key_paths
39
+ @key_paths ||= super.merge COPIED_EVENT_KEY_PATHS
40
+ end
41
+
42
+ def key_types
43
+ @key_types ||= super.merge COPIED_EVENT_KEY_TYPES
44
+ end
45
+
46
+ def key_alias
47
+ @key_alias ||= super.merge COPIED_EVENT_KEY_ALIAS
48
+ end
49
+
50
+ end
51
+ end
@@ -16,6 +16,9 @@
16
16
  limitations under the License.
17
17
  =end
18
18
 
19
- # Exchange Web Service Builders
20
- require 'soap/handsoap/builders/ews_builder.rb'
19
+ module Viewpoint::EWS::Types
21
20
 
21
+ class CreatedEvent < Event
22
+
23
+ end
24
+ end
@@ -16,9 +16,9 @@
16
16
  limitations under the License.
17
17
  =end
18
18
 
19
- module Viewpoint
20
- module EWS
21
- class MeetingResponse < Item
22
- end # MeetingResponse
23
- end # EWS
24
- end # Viewpoint
19
+ module Viewpoint::EWS::Types
20
+
21
+ class DeletedEvent < Event
22
+
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module Viewpoint::EWS::Types
2
+ class DistributionList
3
+ include Viewpoint::EWS
4
+ include Viewpoint::EWS::Types
5
+ include Viewpoint::EWS::Types::Item
6
+ end
7
+ end
@@ -0,0 +1,62 @@
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 Event
22
+ include Viewpoint::EWS
23
+ include Viewpoint::EWS::Types
24
+ include Viewpoint::EWS::Types::Item
25
+
26
+ EVENT_KEY_PATHS = {
27
+ :watermark => [:watermark, :text],
28
+ :timestamp => [:time_stamp, :text],
29
+ :item_id => [:item_id, :attribs],
30
+ :folder_id => [:folder_id, :attribs],
31
+ :parent_folder_id => [:parent_folder_id, :attribs],
32
+ }
33
+
34
+ EVENT_KEY_TYPES = {
35
+ :timestamp => ->(ts){ DateTime.iso8601(ts) }
36
+ }
37
+
38
+ EVENT_KEY_ALIAS = { }
39
+
40
+ def initialize(ews, event)
41
+ @ews = ews
42
+ super(ews, event)
43
+ end
44
+
45
+
46
+ private
47
+
48
+
49
+ def key_paths
50
+ @key_paths ||= EVENT_KEY_PATHS
51
+ end
52
+
53
+ def key_types
54
+ @key_types ||= EVENT_KEY_TYPES
55
+ end
56
+
57
+ def key_alias
58
+ @key_alias ||= EVENT_KEY_ALIAS
59
+ end
60
+
61
+ end
62
+ 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
@@ -16,9 +16,9 @@
16
16
  limitations under the License.
17
17
  =end
18
18
 
19
- module Viewpoint
20
- module EWS
21
- class DistributionList < Item
22
- end # DistributionList
23
- end # EWS
24
- end # Viewpoint
19
+ module Viewpoint::EWS::Types
20
+
21
+ class FreeBusyChangedEvent < Event
22
+
23
+ end
24
+ end
@@ -0,0 +1,352 @@
1
+ require 'ews/item_accessors'
2
+ module Viewpoint::EWS::Types
3
+ module GenericFolder
4
+ include Viewpoint::EWS
5
+ include Viewpoint::EWS::Types
6
+ include Viewpoint::EWS::ItemAccessors
7
+
8
+ GFOLDER_KEY_PATHS = {
9
+ :id => [:folder_id, :attribs, :id],
10
+ :change_key => [:folder_id, :attribs, :change_key],
11
+ :parent_folder_id => [:parent_folder_id, :attribs, :id],
12
+ :parent_folder_change_key => [:parent_folder_id, :attribs, :change_key],
13
+ :folder_class => [:folder_class, :text],
14
+ :total_count => [:total_count, :text],
15
+ :child_folder_count => [:child_folder_count, :text],
16
+ :display_name => [:display_name, :text],
17
+ }
18
+
19
+ GFOLDER_KEY_TYPES = {
20
+ :total_count => ->(str){str.to_i},
21
+ :child_folder_count => ->(str){str.to_i},
22
+ }
23
+
24
+ GFOLDER_KEY_ALIAS = {
25
+ :name => :display_name,
26
+ :ckey => :change_key,
27
+ }
28
+
29
+ attr_accessor :subscription_id, :watermark
30
+
31
+ # @param [SOAP::ExchangeWebService] ews the EWS reference
32
+ # @param [Hash] ews_item the EWS parsed response document
33
+ def initialize(ews, ews_item)
34
+ super
35
+ simplify!
36
+ end
37
+
38
+ def delete!
39
+ opts = {
40
+ :folder_ids => [:id => id],
41
+ :delete_type => 'HardDelete'
42
+ }
43
+ resp = @ews.delete_folder(opts)
44
+ if resp.success?
45
+ true
46
+ else
47
+ raise EwsError, "Could not delete folder. #{resp.code}: #{resp.message}"
48
+ end
49
+ end
50
+
51
+ def items(opts = {})
52
+ args = items_args(opts.clone)
53
+ obj = OpenStruct.new(opts: args, restriction: {})
54
+ yield obj if block_given?
55
+ merge_restrictions! obj
56
+ resp = ews.find_item(args)
57
+ items_parser resp
58
+ end
59
+
60
+ # Fetch items since a give DateTime
61
+ # @param [DateTime] date_time the time to fetch Items since.
62
+ def items_since(date_time, opts = {})
63
+ opts = opts.clone
64
+ unless date_time.kind_of?(Date)
65
+ raise EwsBadArgumentError, "First argument must be a Date or DateTime"
66
+ end
67
+ restr = {:restriction =>
68
+ {:is_greater_than_or_equal_to =>
69
+ [{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
70
+ {:field_uRI_or_constant =>{:constant => {:value=>date_time.to_datetime}}}]
71
+ }}
72
+ items(opts.merge(restr))
73
+ end
74
+
75
+ # Fetch only items from today (since midnight)
76
+ def todays_items(opts = {})
77
+ items_since(Date.today)
78
+ end
79
+
80
+ # Fetch items between a given time period
81
+ # @param [DateTime] start_date the time to start fetching Items from
82
+ # @param [DateTime] end_date the time to stop fetching Items from
83
+ def items_between(start_date, end_date, opts={})
84
+ items do |obj|
85
+ obj.restriction = { :and =>
86
+ [
87
+ {:is_greater_than_or_equal_to =>
88
+ [
89
+ {:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
90
+ {:field_uRI_or_constant=>{:constant => {:value =>start_date}}}
91
+ ]
92
+ },
93
+ {:is_less_than_or_equal_to =>
94
+ [
95
+ {:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
96
+ {:field_uRI_or_constant=>{:constant => {:value =>end_date}}}
97
+ ]
98
+ }
99
+ ]
100
+ }
101
+ end
102
+ end
103
+
104
+ # Search on the item subject
105
+ # @param [String] match_str A simple string paramater to match against the
106
+ # subject. The search ignores case and does not accept regexes... only strings.
107
+ # @param [String,nil] exclude_str A string to exclude from matches against
108
+ # the subject. This is optional.
109
+ def search_by_subject(match_str, exclude_str = nil)
110
+ items do |obj|
111
+ match = {:contains => {
112
+ :containment_mode => 'Substring',
113
+ :containment_comparison => 'IgnoreCase',
114
+ :field_uRI => {:field_uRI=>'item:Subject'},
115
+ :constant => {:value =>match_str}
116
+ }}
117
+ unless exclude_str.nil?
118
+ excl = {:not =>
119
+ {:contains => {
120
+ :containment_mode => 'Substring',
121
+ :containment_comparison => 'IgnoreCase',
122
+ :field_uRI => {:field_uRI=>'item:Subject'},
123
+ :constant => {:value =>exclude_str}
124
+ }}
125
+ }
126
+
127
+ match[:and] = [{:contains => match.delete(:contains)}, excl]
128
+ end
129
+ obj.restriction = match
130
+ end
131
+ end
132
+
133
+ def get_all_properties!
134
+ @ews_item = get_folder(:base_shape => 'AllProperties')
135
+ simplify!
136
+ end
137
+
138
+ def available_categories
139
+ opts = {
140
+ user_config_name: {
141
+ name: 'CategoryList',
142
+ distinguished_folder_id: {id: :calendar}
143
+ },
144
+ user_config_props: 'XmlData'
145
+ }
146
+ resp = ews.get_user_configuration(opts)
147
+ #txt = resp.response_message[:elems][:get_user_configuration_response_message][:elems][1][:user_configuration][:elems][1][:xml_data][:text]
148
+ #Base64.decode64 txt
149
+ end
150
+
151
+ # Subscribe this folder to events. This method initiates an Exchange pull
152
+ # type subscription.
153
+ #
154
+ # @param event_types [Array] Which event types to subscribe to. By default
155
+ # we subscribe to all Exchange event types: :all, :copied, :created,
156
+ # :deleted, :modified, :moved, :new_mail, :free_busy_changed
157
+ # @param watermark [String] pass a watermark if you wish to start the
158
+ # subscription at a specific point.
159
+ # @param timeout [Fixnum] the time in minutes that the subscription can
160
+ # remain idle between calls to #get_events. default: 240 minutes
161
+ # @return [Boolean] Did the subscription happen successfully?
162
+ def subscribe(evtypes = [:all], watermark = nil, timeout = 240)
163
+ # Refresh the subscription if already subscribed
164
+ unsubscribe if subscribed?
165
+
166
+ event_types = normalize_event_names(evtypes)
167
+ folder = {id: self.id, change_key: self.change_key}
168
+ resp = ews.pull_subscribe_folder(folder, event_types, timeout, watermark)
169
+ rmsg = resp.response_messages.first
170
+ if rmsg.success?
171
+ @subscription_id = rmsg.subscription_id
172
+ @watermark = rmsg.watermark
173
+ true
174
+ else
175
+ raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
176
+ end
177
+ end
178
+
179
+ def push_subscribe(url, evtypes = [:all], watermark = nil, status_frequency = nil)
180
+ # Refresh the subscription if already subscribed
181
+ unsubscribe if subscribed?
182
+
183
+ event_types = normalize_event_names(evtypes)
184
+ folder = {id: self.id, change_key: self.change_key}
185
+ resp = ews.push_subscribe_folder(folder, event_types, url, status_frequency, watermark)
186
+ rmsg = resp.response_messages.first
187
+ if rmsg.success?
188
+ @subscription_id = rmsg.subscription_id
189
+ @watermark = rmsg.watermark
190
+ true
191
+ else
192
+ raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
193
+ end
194
+ end
195
+
196
+ # Check if there is a subscription for this folder.
197
+ # @return [Boolean] Are we subscribed to this folder?
198
+ def subscribed?
199
+ ( @subscription_id.nil? or @watermark.nil? )? false : true
200
+ end
201
+
202
+ # Unsubscribe this folder from further Exchange events.
203
+ # @return [Boolean] Did we unsubscribe successfully?
204
+ def unsubscribe
205
+ return true if @subscription_id.nil?
206
+
207
+ resp = ews.unsubscribe(@subscription_id)
208
+ rmsg = resp.response_messages.first
209
+ if rmsg.success?
210
+ @subscription_id, @watermark = nil, nil
211
+ true
212
+ else
213
+ raise EwsSubscriptionError, "Could not unsubscribe: #{rmsg.code}: #{rmsg.message_text}"
214
+ end
215
+ end
216
+
217
+ # Checks a subscribed folder for events
218
+ # @return [Array] An array of Event items
219
+ def get_events
220
+ begin
221
+ if subscribed?
222
+ resp = ews.get_events(@subscription_id, @watermark)
223
+ rmsg = resp.response_messages[0]
224
+ @watermark = rmsg.new_watermark
225
+ # @todo if parms[:more_events] # get more events
226
+ rmsg.events.collect{|ev|
227
+ type = ev.keys.first
228
+ class_by_name(type).new(ews, ev[type])
229
+ }
230
+ else
231
+ raise EwsSubscriptionError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
232
+ end
233
+ rescue EwsSubscriptionTimeout => e
234
+ @subscription_id, @watermark = nil, nil
235
+ raise e
236
+ end
237
+ end
238
+
239
+
240
+ private
241
+
242
+
243
+ def key_paths
244
+ @key_paths ||= super.merge(GFOLDER_KEY_PATHS)
245
+ end
246
+
247
+ def key_types
248
+ @key_types ||= super.merge(GFOLDER_KEY_TYPES)
249
+ end
250
+
251
+ def key_alias
252
+ @key_alias ||= super.merge(GFOLDER_KEY_ALIAS)
253
+ end
254
+
255
+ def simplify!
256
+ @ews_item = @ews_item[:elems].inject({}) do |o,i|
257
+ key = i.keys.first
258
+ if o.has_key?(key)
259
+ if o[key].is_a?(Array)
260
+ o[key] << i[key]
261
+ else
262
+ o[key] = [o.delete(key), i[key]]
263
+ end
264
+ else
265
+ o[key] = i[key]
266
+ end
267
+ o
268
+ end
269
+ end
270
+
271
+ # Get a specific folder by its ID.
272
+ # @param [Hash] opts Misc options to control request
273
+ # @option opts [String] :base_shape IdOnly/Default/AllProperties
274
+ # @raise [EwsError] raised when the backend SOAP method returns an error.
275
+ def get_folder(opts = {})
276
+ args = get_folder_args(opts)
277
+ resp = ews.get_folder(args)
278
+ get_folder_parser(resp)
279
+ end
280
+
281
+ # Build up the arguements for #get_folder
282
+ # @todo: should we really pass the ChangeKey or do we want the freshest obj?
283
+ def get_folder_args(opts)
284
+ opts[:base_shape] ||= 'Default'
285
+ default_args = {
286
+ :folder_ids => [{:id => self.id, :change_key => self.change_key}],
287
+ :folder_shape => {:base_shape => opts[:base_shape]}
288
+ }
289
+ default_args.merge(opts)
290
+ end
291
+
292
+ def get_folder_parser(resp)
293
+ if(resp.status == 'Success')
294
+ f = resp.response_message[:elems][:folders][:elems][0]
295
+ f.values.first
296
+ else
297
+ raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
298
+ end
299
+ end
300
+
301
+ def items_args(opts)
302
+ default_args = {
303
+ :parent_folder_ids => [{:id => self.id}],
304
+ :traversal => 'Shallow',
305
+ :item_shape => {:base_shape => 'Default'}
306
+ }.merge(opts)
307
+ end
308
+
309
+ def items_parser(resp)
310
+ rm = resp.response_messages[0]
311
+ if(rm.status == 'Success')
312
+ items = []
313
+ rm.root_folder.items.each do |i|
314
+ type = i.keys.first
315
+ items << class_by_name(type).new(ews, i[type], self)
316
+ end
317
+ items
318
+ else
319
+ raise EwsError, "Could not retrieve folder. #{rm.code}: #{rm.message_text}"
320
+ end
321
+ end
322
+
323
+ def merge_restrictions!(obj, merge_type = :and)
324
+ if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty?
325
+ obj.opts[:restriction] = {
326
+ merge_type => [
327
+ obj.opts.delete(:restriction),
328
+ obj.restriction
329
+ ]
330
+ }
331
+ elsif !obj.restriction.empty?
332
+ obj.opts[:restriction] = obj.restriction
333
+ end
334
+ end
335
+
336
+ def normalize_event_names(events)
337
+ if events.include?(:all)
338
+ events = [:copied, :created, :deleted, :modified, :moved, :new_mail, :free_busy_changed]
339
+ end
340
+
341
+ events.collect do |ev|
342
+ nev = ev.to_s.ruby_case
343
+ if nev.end_with?('_event')
344
+ nev.to_sym
345
+ else
346
+ "#{nev}_event".to_sym
347
+ end
348
+ end
349
+ end
350
+
351
+ end
352
+ end