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,86 @@
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
+ module Viewpoint::EWS::MessageAccessors
19
+ include Viewpoint::EWS
20
+
21
+ # Send an E-mail message
22
+ #
23
+ # @param [Hash] opts A Hash with message params
24
+ # @option opts [String] :subject The message subject
25
+ # @option opts [String] :body The message body
26
+ # @option opts [Array] :to_recipients An array of e-mail addresses to send to
27
+ # @option opts [Array] :cc_recipients An array of e-mail addresses to send to
28
+ # @option opts [Array] :bcc_recipients An array of e-mail addresses to send to
29
+ # @option opts [Boolean] :draft if true it will save to the draft folder
30
+ # without sending the message.
31
+ # @option opts [String,Symbol,Hash] saved_item_folder_id Either a
32
+ # FolderId(String) or a DistinguishedFolderId(Symbol). You can also pass a
33
+ # Hash in the form: {id: <fold_id>, change_key: <change_key>}
34
+ # @option opts [Array<File>] :file_attachments an Array of File objects
35
+ # @return [Message,Boolean] Returns true if the message is sent, false if
36
+ # nothing is returned from EWS or if draft is true it will return the
37
+ # Message object. Finally, if something goes wrong, it raises an error
38
+ # with a message stating why the e-mail could not be sent.
39
+ # @todo Finish ItemAttachments
40
+ def send_message(opts = {}, &block)
41
+ msg = Template::Message.new opts.clone
42
+ yield msg if block_given?
43
+ if msg.has_attachments?
44
+ draft = msg.draft
45
+ msg.draft = true
46
+ resp = parse_create_item(ews.create_item(msg.to_ews))
47
+ msg.file_attachments.each do |f|
48
+ next unless f.kind_of?(File)
49
+ resp.add_file_attachment(f)
50
+ end
51
+ if draft
52
+ resp.submit_attachments!
53
+ resp
54
+ else
55
+ resp.submit!
56
+ end
57
+ else
58
+ resp = ews.create_item(msg.to_ews)
59
+ resp.response_messages ? parse_create_item(resp) : false
60
+ end
61
+ end
62
+
63
+ # See #send_message for options
64
+ def draft_message(opts = {}, &block)
65
+ send_message opts.merge(draft: true), &block
66
+ end
67
+
68
+
69
+ private
70
+
71
+
72
+ def parse_create_item(resp)
73
+ rm = resp.response_messages[0]
74
+ if(rm.status == 'Success')
75
+ rm.items.empty? ? true : parse_message(rm.items.first)
76
+ else
77
+ raise EwsError, "Could not send message. #{rm.code}: #{rm.message_text}"
78
+ end
79
+ end
80
+
81
+ def parse_message(msg)
82
+ mtype = msg.keys.first
83
+ message = class_by_name(mtype).new(ews, msg[mtype])
84
+ end
85
+
86
+ end # Viewpoint::EWS::MessageAccessors
@@ -0,0 +1,33 @@
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::PushSubscriptionAccessors
20
+ include Viewpoint::EWS
21
+
22
+ def parse_send_notification(msg)
23
+ parser = Viewpoint::EWS::SOAP::EwsParser.new(msg)
24
+ resp = parser.parse response_class: Viewpoint::EWS::SOAP::EwsResponse
25
+ rmsg = resp.response_messages[0]
26
+ if rmsg.success?
27
+ rmsg
28
+ else
29
+ raise EwsSubscriptionError, "#{rmsg.code}: #{rmsg.message_text}"
30
+ end
31
+ end
32
+
33
+ end # Viewpoint::EWS::PushSubscriptionAccessors
@@ -0,0 +1,63 @@
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
+ # This module defines some constants and other niceties to make available to
20
+ # the underlying SOAP classes and modules that do the actual work.
21
+ module Viewpoint
22
+ module EWS
23
+ module SOAP
24
+
25
+ # CONSTANTS
26
+
27
+ NS_SOAP = 'soap'.freeze
28
+ NS_EWS_TYPES = 't'.freeze
29
+ NS_EWS_MESSAGES = 'm'.freeze
30
+ NAMESPACES = {
31
+ "xmlns:#{NS_SOAP}" => 'http://schemas.xmlsoap.org/soap/envelope/',
32
+ "xmlns:#{NS_EWS_TYPES}" => 'http://schemas.microsoft.com/exchange/services/2006/types',
33
+ "xmlns:#{NS_EWS_MESSAGES}" => 'http://schemas.microsoft.com/exchange/services/2006/messages',
34
+ }.freeze
35
+
36
+ # used in ResolveNames to determine where names are resolved
37
+ ActiveDirectory = 'ActiveDirectory'
38
+ ActiveDirectoryContacts = 'ActiveDirectoryContacts'
39
+ Contacts = 'Contacts'
40
+ ContactsActiveDirectory = 'ContactsActiveDirectory'
41
+
42
+ # Target specific Exchange Server versions
43
+ # @see http://msdn.microsoft.com/en-us/library/bb891876(v=exchg.140).aspx
44
+ VERSION_2007 = 'Exchange2007'
45
+ VERSION_2007_SP1 = 'Exchange2007_SP1'
46
+ VERSION_2010 = 'Exchange2010'
47
+ VERSION_2010_SP1 = 'Exchange2010_SP1'
48
+ VERSION_2010_SP2 = 'Exchange2010_SP2'
49
+ VERSION_2013 = 'Exchange2013'
50
+ VERSION_NONE = 'none'
51
+
52
+ HARD_DELETE = 'HardDelete'
53
+ SOFT_DELETE = 'SoftDelete'
54
+ MOVE_TO_DELETED_ITEMS = 'MoveToDeletedItems'
55
+
56
+ def initialize
57
+ @log = Logging.logger[self.class.name.to_s.to_sym]
58
+ @default_ns = NAMESPACES["xmlns:#{NS_EWS_MESSAGES}"]
59
+ end
60
+
61
+ end # SOAP
62
+ end # EWS
63
+ end # Viewpoint
@@ -0,0 +1,1011 @@
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
+ module Viewpoint::EWS::SOAP
19
+
20
+ # This class includes the element builders. The idea is that each element should
21
+ # know how to build themselves so each parent element can delegate creation of
22
+ # subelements to a method of the same name with a '!' after it.
23
+ class EwsBuilder
24
+
25
+ attr_reader :nbuild
26
+ def initialize
27
+ @nbuild = Nokogiri::XML::Builder.new
28
+ end
29
+
30
+ # Build the SOAP envelope and yield this object so subelements can be built. Once
31
+ # you have the EwsBuilder object you can use the nbuild object like shown in the
32
+ # example for the Header section. The nbuild object is the underlying
33
+ # Nokogiri::XML::Builder object.
34
+ # @param [Hash] opts
35
+ # @option opts [String] :server_version The version string that should get
36
+ # set in the Header. See ExchangeWebService#initialize
37
+ # @example
38
+ # xb = EwsBuilder.new
39
+ # xb.build! do |part, b|
40
+ # if(part == :header)
41
+ # b.nbuild.MyVar('blablabla')
42
+ # else
43
+ # b.folder_shape!({:base_shape => 'Default'})
44
+ # end
45
+ # end
46
+ def build!(opts = {}, &block)
47
+ @nbuild.Envelope(NAMESPACES) do |node|
48
+ node.parent.namespace = parent_namespace(node)
49
+ node.Header {
50
+ set_version_header! opts[:server_version]
51
+ yield(:header, self) if block_given?
52
+ }
53
+ node.Body {
54
+ yield(:body, self) if block_given?
55
+ }
56
+ end
57
+ @nbuild.doc
58
+ end
59
+
60
+ # Build XML from a passed in Hash or Array in a specified format.
61
+ # @param [Array,Hash] elems The elements to add to the Builder. They must
62
+ # be specified like so:
63
+ # {:top =>
64
+ # { :xmlns => 'http://stonesthrow/soap',
65
+ # :sub_elements => [
66
+ # {:elem1 => {:text => 'inside'}},
67
+ # {:elem2 => {:text => 'inside2'}}
68
+ # ],
69
+ # :id => '3232', :tx_dd => 23, :asdf => 'turkey'
70
+ # }
71
+ # }
72
+ # or
73
+ # [ {:first => {:text => 'hello'}},
74
+ # {:second => {:text => 'world'}}
75
+ # ]
76
+ #
77
+ # NOTE: there are specialized keys for text (:text), child elements
78
+ # (:sub_elements) and namespaces (:xmlns).
79
+ def build_xml!(elems)
80
+ case elems.class.name
81
+ when 'Hash'
82
+ keys = elems.keys
83
+ vals = elems.values
84
+ if(keys.length > 1 && !vals.is_a?(Hash))
85
+ raise "invalid input: #{elems}"
86
+ end
87
+ vals = vals.first.clone
88
+ se = vals.delete(:sub_elements)
89
+ txt = vals.delete(:text)
90
+
91
+ @nbuild.send(keys.first.to_s.camel_case, txt, vals) {|x|
92
+ build_xml!(se) if se
93
+ }
94
+ when 'Array'
95
+ elems.each do |e|
96
+ build_xml!(e)
97
+ end
98
+ else
99
+ raise "Unsupported type: #{elems.class.name}"
100
+ end
101
+ end
102
+
103
+ # Build the FolderShape element
104
+ # @see http://msdn.microsoft.com/en-us/library/aa494311.aspx
105
+ # @param [Hash] folder_shape The folder shape structure to build from
106
+ # @todo need fully support all options
107
+ def folder_shape!(folder_shape)
108
+ @nbuild.FolderShape {
109
+ @nbuild.parent.default_namespace = @default_ns
110
+ base_shape!(folder_shape[:base_shape])
111
+ if(folder_shape[:additional_properties])
112
+ additional_properties!(folder_shape[:additional_properties])
113
+ end
114
+ }
115
+ end
116
+
117
+ # Build the ItemShape element
118
+ # @see http://msdn.microsoft.com/en-us/library/aa565261.aspx
119
+ # @param [Hash] item_shape The item shape structure to build from
120
+ # @todo need fully support all options
121
+ def item_shape!(item_shape)
122
+ @nbuild[NS_EWS_MESSAGES].ItemShape {
123
+ @nbuild.parent.default_namespace = @default_ns
124
+ base_shape!(item_shape[:base_shape])
125
+ body_type!(item_shape[:body_type]) if item_shape[:body_type]
126
+ if(item_shape[:additional_properties])
127
+ additional_properties!(item_shape[:additional_properties])
128
+ end
129
+ }
130
+ end
131
+
132
+ # Build the BaseShape element
133
+ # @see http://msdn.microsoft.com/en-us/library/aa580545.aspx
134
+ def base_shape!(base_shape)
135
+ @nbuild[NS_EWS_TYPES].BaseShape(base_shape.to_s.camel_case)
136
+ end
137
+
138
+ def body_type!(body_type)
139
+ body_type = body_type.to_s
140
+ if body_type =~ /html/i
141
+ body_type = body_type.upcase
142
+ else
143
+ body_type = body_type.downcase.capitalize
144
+ end
145
+ nbuild[NS_EWS_TYPES].BodyType(body_type)
146
+ end
147
+
148
+ # Build the ParentFolderIds element
149
+ # @see http://msdn.microsoft.com/en-us/library/aa565998.aspx
150
+ def parent_folder_ids!(pfids)
151
+ @nbuild[NS_EWS_MESSAGES].ParentFolderIds {
152
+ pfids.each do |pfid|
153
+ dispatch_folder_id!(pfid)
154
+ end
155
+ }
156
+ end
157
+
158
+ # Build the ParentFolderId element
159
+ # @see http://msdn.microsoft.com/en-us/library/aa563268.aspx
160
+ def parent_folder_id!(pfid)
161
+ @nbuild.ParentFolderId {
162
+ dispatch_folder_id!(pfid)
163
+ }
164
+ end
165
+
166
+ # Build the FolderIds element
167
+ # @see http://msdn.microsoft.com/en-us/library/aa580509.aspx
168
+ def folder_ids!(fids, act_as=nil)
169
+ ns = @nbuild.parent.name.match(/subscription/i) ? NS_EWS_TYPES : NS_EWS_MESSAGES
170
+ @nbuild[ns].FolderIds {
171
+ fids.each do |fid|
172
+ fid[:act_as] = act_as if act_as != nil
173
+ dispatch_folder_id!(fid)
174
+ end
175
+ }
176
+ end
177
+
178
+ # Build the SyncFolderId element
179
+ # @see http://msdn.microsoft.com/en-us/library/aa580296.aspx
180
+ def sync_folder_id!(fid)
181
+ @nbuild.SyncFolderId {
182
+ dispatch_folder_id!(fid)
183
+ }
184
+ end
185
+
186
+ # Build the DistinguishedFolderId element
187
+ # @see http://msdn.microsoft.com/en-us/library/aa580808.aspx
188
+ # @todo add support for the Mailbox child object
189
+ def distinguished_folder_id!(dfid, change_key = nil, act_as = nil)
190
+ attribs = {'Id' => dfid.to_s}
191
+ attribs['ChangeKey'] = change_key if change_key
192
+ @nbuild[NS_EWS_TYPES].DistinguishedFolderId(attribs) {
193
+ if ! act_as.nil?
194
+ mailbox!({:email_address => act_as})
195
+ end
196
+ }
197
+ end
198
+
199
+ # Build the FolderId element
200
+ # @see http://msdn.microsoft.com/en-us/library/aa579461.aspx
201
+ def folder_id!(fid, change_key = nil)
202
+ attribs = {'Id' => fid}
203
+ attribs['ChangeKey'] = change_key if change_key
204
+ @nbuild[NS_EWS_TYPES].FolderId(attribs)
205
+ end
206
+
207
+ # @see http://msdn.microsoft.com/en-us/library/aa563525(v=EXCHG.140).aspx
208
+ def item_ids!(item_ids)
209
+ @nbuild.ItemIds {
210
+ item_ids.each do |iid|
211
+ dispatch_item_id!(iid)
212
+ end
213
+ }
214
+ end
215
+
216
+ def parent_item_id!(id)
217
+ nbuild.ParentItemId {|x|
218
+ x.parent['Id'] = id[:id]
219
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
220
+ }
221
+ end
222
+
223
+ # @see http://msdn.microsoft.com/en-us/library/aa580234(v=EXCHG.140).aspx
224
+ def item_id!(id)
225
+ nbuild[NS_EWS_TYPES].ItemId {|x|
226
+ x.parent['Id'] = id[:id]
227
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
228
+ }
229
+ end
230
+
231
+ # @see http://msdn.microsoft.com/en-us/library/aa580744(v=EXCHG.140).aspx
232
+ def occurrence_item_id!(id)
233
+ @nbuild[NS_EWS_TYPES].OccurrenceItemId {|x|
234
+ x.parent['RecurringMasterId'] = id[:recurring_master_id]
235
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
236
+ x.parent['InstanceIndex'] = id[:instance_index]
237
+ }
238
+ end
239
+
240
+ # @see http://msdn.microsoft.com/en-us/library/aa581019(v=EXCHG.140).aspx
241
+ def recurring_master_item_id!(id)
242
+ @nbuild[NS_EWS_TYPES].RecurringMasterItemId {|x|
243
+ x.parent['OccurrenceId'] = id[:occurrence_id]
244
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
245
+ }
246
+ end
247
+
248
+ # @see http://msdn.microsoft.com/en-us/library/aa565020(v=EXCHG.140).aspx
249
+ def to_folder_id!(to_fid)
250
+ @nbuild[NS_EWS_MESSAGES].ToFolderId {
251
+ dispatch_folder_id!(to_fid)
252
+ }
253
+ end
254
+
255
+ # @see http://msdn.microsoft.com/en-us/library/aa564009.aspx
256
+ def folders!(folders)
257
+ @nbuild.Folders {|x|
258
+ folders.each do |fold|
259
+ fold.each_pair do |ftype, vars| # convenience, should only be one pair
260
+ ftype = "#{ftype}!".to_sym
261
+ if self.respond_to? ftype
262
+ self.send ftype, vars
263
+ else
264
+ raise Viewpoint::EWS::EwsNotImplemented,
265
+ "#{ftype} not implemented as a builder."
266
+ end
267
+ end
268
+ end
269
+ }
270
+ end
271
+
272
+ def folder!(folder, type = :Folder)
273
+ nbuild[NS_EWS_TYPES].send(type) {|x|
274
+ folder.each_pair do |e,v|
275
+ ftype = "#{e}!".to_sym
276
+ if e == :folder_id
277
+ dispatch_folder_id!(v)
278
+ elsif self.respond_to?(ftype)
279
+ self.send ftype, v
280
+ else
281
+ raise Viewpoint::EWS::EwsNotImplemented,
282
+ "#{ftype} not implemented as a builder."
283
+ end
284
+ end
285
+ }
286
+ end
287
+
288
+ def calendar_folder!(folder)
289
+ folder! folder, :CalendarFolder
290
+ end
291
+
292
+ def contacts_folder!(folder)
293
+ folder! folder, :ContactsFolder
294
+ end
295
+
296
+ def search_folder!(folder)
297
+ folder! folder, :SearchFolder
298
+ end
299
+
300
+ def tasks_folder!(folder)
301
+ folder! folder, :TasksFolder
302
+ end
303
+
304
+ def display_name!(name)
305
+ nbuild[NS_EWS_TYPES].DisplayName(name)
306
+ end
307
+
308
+ # Build the AdditionalProperties element
309
+ # @see http://msdn.microsoft.com/en-us/library/aa563810.aspx
310
+ def additional_properties!(addprops)
311
+ @nbuild[NS_EWS_TYPES].AdditionalProperties {
312
+ addprops.each_pair {|k,v|
313
+ dispatch_field_uri!({k => v})
314
+ }
315
+ }
316
+ end
317
+
318
+ # Build the Mailbox element.
319
+ # This element is commonly used for delegation. Typically passing an
320
+ # email_address is sufficient
321
+ # @see http://msdn.microsoft.com/en-us/library/aa565036.aspx
322
+ # @param [Hash] mailbox A well-formated hash
323
+ def mailbox!(mbox)
324
+ nbuild[NS_EWS_TYPES].Mailbox {
325
+ name!(mbox[:name]) if mbox[:name]
326
+ email_address!(mbox[:email_address]) if mbox[:email_address]
327
+ address!(mbox[:address]) if mbox[:address] # for Availability query
328
+ routing_type!(mbox[:routing_type]) if mbox[:routing_type]
329
+ mailbox_type!(mbox[:mailbox_type]) if mbox[:mailbox_type]
330
+ item_id!(mbox[:item_id]) if mbox[:item_id]
331
+ }
332
+ end
333
+
334
+ def name!(name)
335
+ nbuild[NS_EWS_TYPES].Name(name)
336
+ end
337
+
338
+ def email_address!(email)
339
+ nbuild[NS_EWS_TYPES].EmailAddress(email)
340
+ end
341
+
342
+ def address!(email)
343
+ nbuild[NS_EWS_TYPES].Address(email)
344
+ end
345
+
346
+ # This is stupid. The only valid value is "SMTP"
347
+ def routing_type!(type)
348
+ nbuild[NS_EWS_TYPES].RoutingType(type)
349
+ end
350
+
351
+ def mailbox_type!(type)Standard
352
+ nbuild[NS_EWS_TYPES].MailboxType(type)
353
+ end
354
+
355
+ def user_oof_settings!(opts)
356
+ nbuild[NS_EWS_TYPES].UserOofSettings {
357
+ nbuild.OofState(opts[:oof_state].to_s.camel_case)
358
+ nbuild.ExternalAudience(opts[:external_audience].to_s.camel_case) if opts[:external_audience]
359
+ duration!(opts[:duration]) if opts[:duration]
360
+ nbuild.InternalReply {
361
+ nbuild.Message(opts[:internal_reply])
362
+ } if opts[:external_reply]
363
+ nbuild.ExternalReply {
364
+ nbuild.Message(opts[:external_reply])
365
+ } if opts[:external_reply]
366
+ }
367
+ end
368
+
369
+ def duration!(opts)
370
+ nbuild.Duration {
371
+ nbuild.StartTime(opts[:start_time].new_offset(0).strftime('%FT%H:%M:%SZ'))
372
+ nbuild.EndTime(opts[:end_time].new_offset(0).strftime('%FT%H:%M:%SZ'))
373
+ }
374
+ end
375
+
376
+ def mailbox_data!(md)
377
+ nbuild[NS_EWS_TYPES].MailboxData {
378
+ nbuild.Email {
379
+ mbox = md[:email]
380
+ name!(mbox[:name]) if mbox[:name]
381
+ address!(mbox[:address]) if mbox[:address] # for Availability query
382
+ routing_type!(mbox[:routing_type]) if mbox[:routing_type]
383
+ }
384
+ nbuild.AttendeeType 'Required'
385
+ }
386
+ end
387
+
388
+ def free_busy_view_options!(opts)
389
+ nbuild[NS_EWS_TYPES].FreeBusyViewOptions {
390
+ nbuild.TimeWindow {
391
+ nbuild.StartTime(opts[:time_window][:start_time])
392
+ nbuild.EndTime(opts[:time_window][:end_time])
393
+ }
394
+ nbuild.RequestedView(opts[:requested_view][:requested_free_busy_view].to_s.camel_case)
395
+ }
396
+ end
397
+
398
+ def suggestions_view_options!(opts)
399
+ end
400
+
401
+ def time_zone!(zone)
402
+ nbuild[NS_EWS_TYPES].TimeZone {
403
+ nbuild.Bias(480)
404
+ nbuild.StandardTime {
405
+ nbuild.Bias(0)
406
+ nbuild.Time("02:00:00")
407
+ nbuild.DayOrder(5)
408
+ nbuild.Month(10)
409
+ nbuild.DayOfWeek('Sunday')
410
+ }
411
+ nbuild.DaylightTime {
412
+ nbuild.Bias(-60)
413
+ nbuild.Time("02:00:00")
414
+ nbuild.DayOrder(1)
415
+ nbuild.Month(4)
416
+ nbuild.DayOfWeek('Sunday')
417
+ }
418
+ }
419
+ end
420
+
421
+ # Build the Restriction element
422
+ # @see http://msdn.microsoft.com/en-us/library/aa563791.aspx
423
+ # @param [Hash] restriction a well-formatted Hash that can be fed to #build_xml!
424
+ def restriction!(restriction)
425
+ @nbuild[NS_EWS_MESSAGES].Restriction {
426
+ restriction.each_pair do |k,v|
427
+ self.send normalize_type(k), v
428
+ end
429
+ }
430
+ end
431
+
432
+ def and_r(expr)
433
+ and_or('And', expr)
434
+ end
435
+
436
+ def or_r(expr)
437
+ and_or('Or', expr)
438
+ end
439
+
440
+ def and_or(type, expr)
441
+ @nbuild[NS_EWS_TYPES].send(type) {
442
+ expr.each do |e|
443
+ type = e.keys.first
444
+ self.send normalize_type(type), e[type]
445
+ end
446
+ }
447
+ end
448
+
449
+ def not_r(expr)
450
+ @nbuild[NS_EWS_TYPES].Not {
451
+ type = expr.keys.first
452
+ self.send(type, expr[type])
453
+ }
454
+ end
455
+
456
+ def contains(expr)
457
+ @nbuild[NS_EWS_TYPES].Contains(
458
+ 'ContainmentMode' => expr.delete(:containment_mode),
459
+ 'ContainmentComparison' => expr.delete(:containment_comparison)) {
460
+ c = expr.delete(:constant) # remove constant 1st for ordering
461
+ type = expr.keys.first
462
+ self.send(type, expr[type])
463
+ constant(c)
464
+ }
465
+ end
466
+
467
+ def excludes(expr)
468
+ @nbuild[NS_EWS_TYPES].Excludes {
469
+ b = expr.delete(:bitmask) # remove bitmask 1st for ordering
470
+ type = expr.keys.first
471
+ self.send(type, expr[type])
472
+ bitmask(b)
473
+ }
474
+ end
475
+
476
+ def exists(expr)
477
+ @nbuild[NS_EWS_TYPES].Exists {
478
+ type = expr.keys.first
479
+ self.send(type, expr[type])
480
+ }
481
+ end
482
+
483
+ def bitmask(expr)
484
+ @nbuild[NS_EWS_TYPES].Bitmask('Value' => expr[:value])
485
+ end
486
+
487
+ def is_equal_to(expr)
488
+ restriction_compare('IsEqualTo',expr)
489
+ end
490
+
491
+ def is_greater_than(expr)
492
+ restriction_compare('IsGreaterThan',expr)
493
+ end
494
+
495
+ def is_greater_than_or_equal_to(expr)
496
+ restriction_compare('IsGreaterThanOrEqualTo',expr)
497
+ end
498
+
499
+ def is_less_than(expr)
500
+ restriction_compare('IsLessThan',expr)
501
+ end
502
+
503
+ def is_less_than_or_equal_to(expr)
504
+ restriction_compare('IsLessThanOrEqualTo',expr)
505
+ end
506
+
507
+ def is_not_equal_to(expr)
508
+ restriction_compare('IsNotEqualTo',expr)
509
+ end
510
+
511
+ def restriction_compare(type,expr)
512
+ nbuild[NS_EWS_TYPES].send(type) {
513
+ expr.each do |e|
514
+ e.each_pair do |k,v|
515
+ self.send(k, v)
516
+ end
517
+ end
518
+ }
519
+ end
520
+
521
+ def field_uRI(expr)
522
+ nbuild[NS_EWS_TYPES].FieldURI('FieldURI' => expr[:field_uRI])
523
+ end
524
+
525
+ def indexed_field_uRI(expr)
526
+ nbuild[NS_EWS_TYPES].IndexedFieldURI(
527
+ 'FieldURI' => expr[:field_uRI],
528
+ 'FieldIndex' => expr[:field_index]
529
+ )
530
+ end
531
+
532
+ def extended_field_uRI(expr)
533
+ nbuild[NS_EWS_TYPES].ExtendedFieldURI {
534
+ nbuild.parent['DistinguishedPropertySetId'] = expr[:distinguished_property_set_id] if expr[:distinguished_property_set_id]
535
+ nbuild.parent['PropertySetId'] = expr[:property_set_id] if expr[:property_set_id]
536
+ nbuild.parent['PropertyTag'] = expr[:property_tag] if expr[:property_tag]
537
+ nbuild.parent['PropertyName'] = expr[:property_name] if expr[:property_name]
538
+ nbuild.parent['PropertyId'] = expr[:property_id] if expr[:property_id]
539
+ nbuild.parent['PropertyType'] = expr[:property_type] if expr[:property_type]
540
+ }
541
+ end
542
+
543
+ def field_uRI_or_constant(expr)
544
+ nbuild[NS_EWS_TYPES].FieldURIOrConstant {
545
+ type = expr.keys.first
546
+ self.send(type, expr[type])
547
+ }
548
+ end
549
+
550
+ def constant(expr)
551
+ nbuild[NS_EWS_TYPES].Constant('Value' => expr[:value])
552
+ end
553
+
554
+ # Build the CalendarView element
555
+ def calendar_view!(cal_view)
556
+ attribs = {}
557
+ cal_view.each_pair {|k,v| attribs[k.to_s.camel_case] = v.to_s}
558
+ @nbuild[NS_EWS_MESSAGES].CalendarView(attribs)
559
+ end
560
+
561
+ # Build the ContactsView element
562
+ def contacts_view!(con_view)
563
+ attribs = {}
564
+ con_view.each_pair {|k,v| attribs[k.to_s.camel_case] = v.to_s}
565
+ @nbuild[NS_EWS_MESSAGES].ContactsView(attribs)
566
+ end
567
+
568
+ # @see http://msdn.microsoft.com/en-us/library/aa579678(v=EXCHG.140).aspx
569
+ def event_types!(evtypes)
570
+ @nbuild[NS_EWS_TYPES].EventTypes {
571
+ evtypes.each do |et|
572
+ @nbuild[NS_EWS_TYPES].EventType(et.to_s.camel_case)
573
+ end
574
+ }
575
+ end
576
+
577
+ # @see http://msdn.microsoft.com/en-us/library/aa565886(v=EXCHG.140).aspx
578
+ def watermark!(wmark, ns = NS_EWS_TYPES)
579
+ @nbuild[ns].Watermark(wmark)
580
+ end
581
+
582
+ # @see http://msdn.microsoft.com/en-us/library/aa565201(v=EXCHG.140).aspx
583
+ def timeout!(tout)
584
+ @nbuild[NS_EWS_TYPES].Timeout(tout)
585
+ end
586
+
587
+ # @see http://msdn.microsoft.com/en-us/library/aa564048(v=EXCHG.140).aspx
588
+ def status_frequency!(freq)
589
+ @nbuild[NS_EWS_TYPES].StatusFrequency(freq)
590
+ end
591
+
592
+ # @see http://msdn.microsoft.com/en-us/library/aa566309(v=EXCHG.140).aspx
593
+ def uRL!(url)
594
+ @nbuild[NS_EWS_TYPES].URL(url)
595
+ end
596
+
597
+ # @see http://msdn.microsoft.com/en-us/library/aa563790(v=EXCHG.140).aspx
598
+ def subscription_id!(subid)
599
+ @nbuild.SubscriptionId(subid)
600
+ end
601
+
602
+ # @see http://msdn.microsoft.com/en-us/library/aa563455(v=EXCHG.140).aspx
603
+ def pull_subscription_request(subopts)
604
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
605
+ @nbuild.PullSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
606
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
607
+ event_types!(subopts[:event_types]) if subopts[:event_types]
608
+ watermark!(subopts[:watermark]) if subopts[:watermark]
609
+ timeout!(subopts[:timeout]) if subopts[:timeout]
610
+ }
611
+ end
612
+
613
+ # @see http://msdn.microsoft.com/en-us/library/aa563599(v=EXCHG.140).aspx
614
+ def push_subscription_request(subopts)
615
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
616
+ @nbuild.PushSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
617
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
618
+ event_types!(subopts[:event_types]) if subopts[:event_types]
619
+ watermark!(subopts[:watermark]) if subopts[:watermark]
620
+ status_frequency!(subopts[:status_frequency]) if subopts[:status_frequency]
621
+ uRL!(subopts[:uRL]) if subopts[:uRL]
622
+ }
623
+ end
624
+
625
+ # @see http://msdn.microsoft.com/en-us/library/ff406182(v=EXCHG.140).aspx
626
+ def streaming_subscription_request(subopts)
627
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
628
+ @nbuild.StreamingSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
629
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
630
+ event_types!(subopts[:event_types]) if subopts[:event_types]
631
+ }
632
+ end
633
+
634
+ # @see http://msdn.microsoft.com/en-us/library/aa565970(v=EXCHG.140).aspx
635
+ def sync_state!(syncstate)
636
+ @nbuild.SyncState(syncstate)
637
+ end
638
+
639
+ # @see http://msdn.microsoft.com/en-us/library/aa563785(v=EXCHG.140).aspx
640
+ def ignore!(item_ids)
641
+ @nbuild.Ignore {
642
+ item_ids.each do |iid|
643
+ item_id!(iid)
644
+ end
645
+ }
646
+ end
647
+
648
+ # @see http://msdn.microsoft.com/en-us/library/aa566325(v=EXCHG.140).aspx
649
+ def max_changes_returned!(cnum)
650
+ @nbuild[NS_EWS_MESSAGES].MaxChangesReturned(cnum)
651
+ end
652
+
653
+ # @see http://msdn.microsoft.com/en-us/library/dd899531(v=EXCHG.140).aspx
654
+ def sync_scope!(scope)
655
+ @nbuild.SyncScope(scope)
656
+ end
657
+
658
+ # @see http://msdn.microsoft.com/en-us/library/aa580758(v=EXCHG.140).aspx
659
+ def saved_item_folder_id!(fid)
660
+ @nbuild.SavedItemFolderId {
661
+ dispatch_folder_id!(fid)
662
+ }
663
+ end
664
+
665
+ # @see http://msdn.microsoft.com/en-us/library/aa565652(v=exchg.140).aspx
666
+ def item!(item)
667
+ nbuild.Item {
668
+ item.each_pair {|k,v|
669
+ self.send("#{k}!", v)
670
+ }
671
+ }
672
+ end
673
+
674
+ def message!(item)
675
+ nbuild[NS_EWS_TYPES].Message {
676
+ item.each_pair {|k,v|
677
+ self.send("#{k}!", v)
678
+ }
679
+ }
680
+ end
681
+
682
+ def calendar_item!(item)
683
+ nbuild[NS_EWS_TYPES].CalendarItem {
684
+ item.each_pair {|k,v|
685
+ self.send("#{k}!", v)
686
+ }
687
+ }
688
+ end
689
+
690
+ def forward_item!(item)
691
+ nbuild[NS_EWS_TYPES].ForwardItem {
692
+ item.each_pair {|k,v|
693
+ self.send("#{k}!", v)
694
+ }
695
+ }
696
+ end
697
+
698
+ def reply_to_item!(item)
699
+ nbuild[NS_EWS_TYPES].ReplyToItem {
700
+ item.each_pair {|k,v|
701
+ self.send("#{k}!", v)
702
+ }
703
+ }
704
+ end
705
+
706
+ def reply_all_to_item!(item)
707
+ nbuild[NS_EWS_TYPES].ReplyAllToItem {
708
+ item.each_pair {|k,v|
709
+ self.send("#{k}!", v)
710
+ }
711
+ }
712
+ end
713
+
714
+ def reference_item_id!(id)
715
+ nbuild[NS_EWS_TYPES].ReferenceItemId {|x|
716
+ x.parent['Id'] = id[:id]
717
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
718
+ }
719
+ end
720
+
721
+ def subject!(sub)
722
+ nbuild[NS_EWS_TYPES].Subject(sub)
723
+ end
724
+
725
+ def body!(b)
726
+ nbuild[NS_EWS_TYPES].Body(b[:text]) {|x|
727
+ x.parent['BodyType'] = b[:body_type] if b[:body_type]
728
+ }
729
+ end
730
+
731
+ def new_body_content!(b)
732
+ nbuild[NS_EWS_TYPES].NewBodyContent(b[:text]) {|x|
733
+ x.parent['BodyType'] = b[:body_type] if b[:body_type]
734
+ }
735
+ end
736
+
737
+ # @see http://msdn.microsoft.com/en-us/library/aa563719(v=exchg.140).aspx
738
+ # @param [Array] r An array of Mailbox type hashes to send to #mailbox!
739
+ def to_recipients!(r)
740
+ nbuild[NS_EWS_TYPES].ToRecipients {
741
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
742
+ }
743
+ end
744
+
745
+ def cc_recipients!(r)
746
+ nbuild[NS_EWS_TYPES].CcRecipients {
747
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
748
+ }
749
+ end
750
+
751
+ def bcc_recipients!(r)
752
+ nbuild[NS_EWS_TYPES].BccRecipients {
753
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
754
+ }
755
+ end
756
+
757
+ def required_attendees!(attendees)
758
+ nbuild[NS_EWS_TYPES].RequiredAttendees {
759
+ attendees.each {|a| attendee!(a[:attendee])}
760
+ }
761
+ end
762
+
763
+ def optional_attendees!(attendees)
764
+ nbuild[NS_EWS_TYPES].OptionalAttendees {
765
+ attendees.each {|a| attendee!(a[:attendee])}
766
+ }
767
+ end
768
+
769
+ def resources!(attendees)
770
+ nbuild[NS_EWS_TYPES].Resources {
771
+ attendees.each {|a| attendee!(a[:attendee])}
772
+ }
773
+ end
774
+
775
+ def attendee!(a)
776
+ nbuild[NS_EWS_TYPES].Attendee {
777
+ mailbox!(a[:mailbox])
778
+ #@todo support ResponseType, LastResponseTime: http://msdn.microsoft.com/en-us/library/aa580339.aspx
779
+ }
780
+ end
781
+
782
+ def start!(st)
783
+ nbuild[NS_EWS_TYPES].Start(st[:text])
784
+ end
785
+
786
+ def end!(et)
787
+ nbuild[NS_EWS_TYPES].End(et[:text])
788
+ end
789
+
790
+ # @see http://msdn.microsoft.com/en-us/library/aa565428(v=exchg.140).aspx
791
+ def item_changes!(changes)
792
+ nbuild.ItemChanges {
793
+ changes.each do |chg|
794
+ item_change!(chg)
795
+ end
796
+ }
797
+ end
798
+
799
+ # @see http://msdn.microsoft.com/en-us/library/aa581081(v=exchg.140).aspx
800
+ def item_change!(change)
801
+ @nbuild[NS_EWS_TYPES].ItemChange {
802
+ updates = change.delete(:updates) # Remove updates so dispatch_item_id works correctly
803
+ dispatch_item_id!(change)
804
+ updates!(updates)
805
+ }
806
+ end
807
+
808
+ # @see http://msdn.microsoft.com/en-us/library/aa581074(v=exchg.140).aspx
809
+ def updates!(updates)
810
+ @nbuild[NS_EWS_TYPES].Updates {
811
+ updates.each do |update|
812
+ dispatch_update_type!(update)
813
+ end
814
+ }
815
+ end
816
+
817
+ # @see http://msdn.microsoft.com/en-us/library/aa581317(v=exchg.140).aspx
818
+ def append_to_item_field!(upd)
819
+ uri = upd.select {|k,v| k =~ /_uri/i}
820
+ raise EwsBadArgumentError, "Bad argument given for AppendToItemField." if uri.keys.length != 1
821
+ upd.delete(uri.keys.first)
822
+ @nbuild.AppendToItemField {
823
+ dispatch_field_uri!(uri)
824
+ dispatch_field_item!(upd)
825
+ }
826
+ end
827
+
828
+ # @see http://msdn.microsoft.com/en-us/library/aa581487(v=exchg.140).aspx
829
+ def set_item_field!(upd)
830
+ uri = upd.select {|k,v| k =~ /_uri/i}
831
+ raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
832
+ upd.delete(uri.keys.first)
833
+ @nbuild.SetItemField {
834
+ dispatch_field_uri!(uri)
835
+ dispatch_field_item!(upd)
836
+ }
837
+ end
838
+
839
+ # @see http://msdn.microsoft.com/en-us/library/aa580330(v=exchg.140).aspx
840
+ def delete_item_field!(upd)
841
+ uri = upd.select {|k,v| k =~ /_uri/i}
842
+ raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
843
+ @nbuild.DeleteItemField {
844
+ dispatch_field_uri!(uri)
845
+ }
846
+ end
847
+
848
+ # @see http://msdn.microsoft.com/en-us/library/ff709497(v=exchg.140).aspx
849
+ def return_new_item_ids!(retval)
850
+ @nbuild.ReturnNewItemIds(retval)
851
+ end
852
+
853
+ def file_attachment!(fa)
854
+ @nbuild[NS_EWS_TYPES].FileAttachment {
855
+ @nbuild.Name(fa.name)
856
+ @nbuild.Content(fa.content)
857
+ }
858
+ end
859
+
860
+ def item_attachment!(ia)
861
+ @nbuild[NS_EWS_TYPES].ItemAttachment {
862
+ @nbuild.Name(ia.name)
863
+ @nbuild.Item {
864
+ item_id!(ia.item)
865
+ }
866
+ }
867
+ end
868
+
869
+ # Build the AttachmentIds element
870
+ # @see http://msdn.microsoft.com/en-us/library/aa580686.aspx
871
+ def attachment_ids!(aids)
872
+ @nbuild.AttachmentIds {
873
+ @nbuild.parent.default_namespace = @default_ns
874
+ aids.each do |aid|
875
+ attachment_id!(aid)
876
+ end
877
+ }
878
+ end
879
+
880
+ # Build the AttachmentId element
881
+ # @see http://msdn.microsoft.com/en-us/library/aa580764.aspx
882
+ def attachment_id!(aid)
883
+ attribs = {'Id' => aid}
884
+ @nbuild[NS_EWS_TYPES].AttachmentId(attribs)
885
+ end
886
+
887
+ def user_configuration_name!(cfg_name)
888
+ attribs = {'Name' => cfg_name.delete(:name)}
889
+ @nbuild[NS_EWS_MESSAGES].UserConfigurationName(attribs) {
890
+ fid = cfg_name.keys.first
891
+ self.send "#{fid}!", cfg_name[fid][:id], cfg_name[fid][:change_key]
892
+ }
893
+ end
894
+
895
+ def user_configuration_properties!(cfg_prop)
896
+ @nbuild[NS_EWS_MESSAGES].UserConfigurationProperties(cfg_prop)
897
+ end
898
+
899
+ # ---------------------- Helpers -------------------- #
900
+
901
+ # A helper method to dispatch to a FolderId or DistinguishedFolderId correctly
902
+ # @param [Hash] fid A folder_id
903
+ # Ex: {:id => myid, :change_key => ck}
904
+ def dispatch_folder_id!(fid)
905
+ if(fid[:id].is_a?(String))
906
+ folder_id!(fid[:id], fid[:change_key])
907
+ elsif(fid[:id].is_a?(Symbol))
908
+ distinguished_folder_id!(fid[:id], fid[:change_key], fid[:act_as])
909
+ else
910
+ raise EwsBadArgumentError, "Bad argument given for a FolderId. #{fid[:id].class}"
911
+ end
912
+ end
913
+
914
+ # A helper method to dispatch to an ItemId, OccurrenceItemId, or a RecurringMasterItemId
915
+ # @param [Hash] iid The item id of some type
916
+ def dispatch_item_id!(iid)
917
+ type = iid.keys.first
918
+ item = iid[type]
919
+ case type
920
+ when :item_id
921
+ item_id!(item)
922
+ when :occurrence_item_id
923
+ occurrence_item_id!(
924
+ item[:recurring_master_id], item[:change_key], item[:instance_index])
925
+ when :recurring_master_item_id
926
+ recurring_master_item_id!(item[:occurrence_id], item[:change_key])
927
+ else
928
+ raise EwsBadArgumentError, "Bad ItemId type. #{type}"
929
+ end
930
+ end
931
+
932
+ # A helper method to dispatch to a AppendToItemField, SetItemField, or
933
+ # DeleteItemField
934
+ # @param [Hash] update An update of some type
935
+ def dispatch_update_type!(update)
936
+ type = update.keys.first
937
+ upd = update[type]
938
+ case type
939
+ when :append_to_item_field
940
+ append_to_item_field!(upd)
941
+ when :set_item_field
942
+ set_item_field!(upd)
943
+ when :delete_item_field
944
+ delete_item_field!(upd)
945
+ else
946
+ raise EwsBadArgumentError, "Bad Update type. #{type}"
947
+ end
948
+ end
949
+
950
+ # A helper to dispatch to a FieldURI, IndexedFieldURI, or an ExtendedFieldURI
951
+ # @todo Implement ExtendedFieldURI
952
+ def dispatch_field_uri!(uri)
953
+ type = uri.keys.first
954
+ vals = uri[type].is_a?(Array) ? uri[type] : [uri[type]]
955
+ case type
956
+ when :field_uRI, :field_uri
957
+ vals.each do |val|
958
+ nbuild.FieldURI('FieldURI' => val[:field_uRI])
959
+ end
960
+ when :indexed_field_uRI, :indexed_field_uri
961
+ vals.each do |val|
962
+ nbuild.IndexedFieldURI('FieldURI' => val[:field_uRI], 'FieldIndex' => val[:field_index])
963
+ end
964
+ when :extended_field_uRI, :extended_field_uri
965
+ vals.each do |val|
966
+ nbuild.ExtendedFieldURI {
967
+ nbuild.parent['DistinguishedPropertySetId'] = val[:distinguished_property_set_id] if val[:distinguished_property_set_id]
968
+ nbuild.parent['PropertySetId'] = val[:property_set_id] if val[:property_set_id]
969
+ nbuild.parent['PropertyTag'] = val[:property_tag] if val[:property_tag]
970
+ nbuild.parent['PropertyName'] = val[:property_name] if val[:property_name]
971
+ nbuild.parent['PropertyId'] = val[:property_id] if val[:property_id]
972
+ nbuild.parent['PropertyType'] = val[:property_type] if val[:property_type]
973
+ }
974
+ end
975
+ else
976
+ raise EwsBadArgumentError, "Bad URI type. #{type}"
977
+ end
978
+
979
+ end
980
+
981
+ def dispatch_field_item!(item)
982
+ build_xml!(item)
983
+ end
984
+
985
+
986
+ private
987
+
988
+ def parent_namespace(node)
989
+ node.parent.namespace_definitions.find {|ns| ns.prefix == NS_SOAP}
990
+ end
991
+
992
+ def set_version_header!(version)
993
+ if version && !(version == 'none')
994
+ nbuild[NS_EWS_TYPES].RequestServerVersion {|x|
995
+ x.parent['Version'] = version
996
+ }
997
+ end
998
+ end
999
+
1000
+ # some methods need special naming so they use the '_r' suffix like 'and'
1001
+ def normalize_type(type)
1002
+ case type
1003
+ when :and, :or, :not
1004
+ "#{type}_r".to_sym
1005
+ else
1006
+ type
1007
+ end
1008
+ end
1009
+
1010
+ end # EwsBuilder
1011
+ end # Viewpoint::EWS::SOAP