rews 0.1.0 → 0.2.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.
- data/README.rdoc +6 -0
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/rews/client.rb +48 -0
- data/lib/rews/folder.rb +84 -38
- data/lib/rews/item.rb +39 -19
- data/lib/rews/restriction.rb +11 -6
- data/lib/rews/shape.rb +9 -0
- data/lib/rews/sort_order.rb +7 -3
- data/lib/rews/util.rb +14 -7
- data/lib/rews/view.rb +8 -0
- data/lib/rews.rb +1 -33
- data/spec/request_proxy.rb +18 -0
- data/spec/rews/client_spec.rb +21 -0
- data/spec/rews/folder_spec.rb +402 -0
- data/spec/rews/item_spec.rb +124 -0
- data/spec/rews/restriction_spec.rb +53 -0
- data/spec/rews/shape_spec.rb +36 -0
- data/spec/rews/sort_order_spec.rb +56 -0
- data/spec/rews/util_spec.rb +103 -0
- data/spec/rews/view_spec.rb +35 -0
- data/spec/spec_helper.rb +2 -0
- metadata +43 -9
- data/spec/rews_spec.rb +0 -4
data/README.rdoc
CHANGED
@@ -35,6 +35,12 @@ to use :
|
|
35
35
|
|
36
36
|
== Install
|
37
37
|
|
38
|
+
to use NTLM authentication, you need versions of httpclient and ntlm-http
|
39
|
+
gems with fixes for NTLM authentication
|
40
|
+
|
41
|
+
* httpclient branch ntlm_domain : https://github.com/mccraigmccraig/httpclient/tree/ntlm_domain
|
42
|
+
* ntlm-http branch fix_unicode : https://github.com/trampoline/ntlm-http/tree/fix_unicode
|
43
|
+
|
38
44
|
gem install rews
|
39
45
|
|
40
46
|
== Note on Patches/Pull Requests
|
data/Rakefile
CHANGED
@@ -11,11 +11,12 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/trampoline/rews"
|
12
12
|
gem.authors = ["Trampoline Systems Ltd"]
|
13
13
|
gem.add_dependency "savon", ">= 0.8.6"
|
14
|
-
gem.add_dependency "ntlm-http", ">= 0.1.1"
|
14
|
+
gem.add_dependency "ntlm-http", ">= 0.1.1.1"
|
15
15
|
gem.add_dependency "httpclient", ">= 2.1.6.1.1"
|
16
16
|
gem.add_dependency "fetch_in", ">= 0.2.0"
|
17
17
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
18
18
|
gem.add_development_dependency "rr", ">= 0.10.5"
|
19
|
+
gem.add_development_dependency "nokogiri", ">= 1.4.4"
|
19
20
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
21
|
end
|
21
22
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/rews/client.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rews
|
2
|
+
class Client
|
3
|
+
attr_reader :client
|
4
|
+
attr_accessor :logdev
|
5
|
+
|
6
|
+
# create a +Client+ to access Exchange Web Services
|
7
|
+
# * using NTLM authentication
|
8
|
+
# Rews::Client.new('https://exchange.foo.com/EWS/Exchange.asmx', :ntlm, 'DOMAIN\\user', 'password')
|
9
|
+
# * using basic authentication
|
10
|
+
# Rews::Client.new('https://exchange.foo.com/EWS/Exchange.asmx', :basic, 'DOMAIN\\user', 'password')
|
11
|
+
def initialize(endpoint, auth_type, user, password)
|
12
|
+
@endpoint=endpoint
|
13
|
+
@auth_type = auth_type
|
14
|
+
@user=user
|
15
|
+
@password=password
|
16
|
+
@client = Savon::Client.new do
|
17
|
+
wsdl.endpoint = endpoint
|
18
|
+
wsdl.namespace = SCHEMA_MESSAGES
|
19
|
+
|
20
|
+
http.auth.ssl.verify_mode = :none
|
21
|
+
http.auth.send(auth_type, user, password)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
"#<#{self.class} @endpoint=#{@endpoint}, @auth_type=#{@auth_type}, @user=#{@user}, @password=#{@password}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
# get a <tt>Folder::DistinguishedFolderId</tt> referencing one of the named top-level Folders in an Exchange mailbox
|
30
|
+
# * get a folder from the default mailbox
|
31
|
+
# client.distinguished_folder_id('inbox')
|
32
|
+
# * get a folder from another mailbox
|
33
|
+
# client.distinguished_folder_id('inbox', 'foo@bar.com')
|
34
|
+
def distinguished_folder_id(id, mailbox_email=nil)
|
35
|
+
Folder::DistinguishedFolderId.new(client, id, mailbox_email)
|
36
|
+
end
|
37
|
+
|
38
|
+
# yield a +Logger+ if +logdev+ has been set
|
39
|
+
def log
|
40
|
+
yield logger if @logdev
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger
|
44
|
+
return @logger if @logger
|
45
|
+
@logger = Logger.new(@logdev) if @logdev
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rews/folder.rb
CHANGED
@@ -1,24 +1,41 @@
|
|
1
1
|
module Rews
|
2
2
|
module Folder
|
3
|
+
|
4
|
+
# represents a Folder in a mailbox on an Exchange server
|
3
5
|
class Folder
|
4
6
|
attr_reader :client
|
5
7
|
attr_reader :folder_id
|
6
8
|
attr_reader :attributes
|
7
9
|
|
8
10
|
def initialize(client, folder)
|
11
|
+
@client = client
|
9
12
|
@folder_id = VanillaFolderId.new(client, folder[:folder_id])
|
10
13
|
@attributes = folder
|
11
14
|
end
|
12
15
|
|
16
|
+
def ==(other)
|
17
|
+
other.is_a?(Folder) &&
|
18
|
+
@client == other.client &&
|
19
|
+
@folder_id == other.folder_id &&
|
20
|
+
@attributes == other.attributes
|
21
|
+
end
|
22
|
+
|
23
|
+
# access the +Folder+ +attributes+
|
13
24
|
def [](key)
|
14
25
|
@attributes[key]
|
15
26
|
end
|
16
27
|
|
28
|
+
# keys of the +Folder+ +attributes+
|
17
29
|
def keys
|
18
30
|
@attributes.keys
|
19
31
|
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<#{self.class} @folder_id=#{@folder_id.inspect}, @attributes=#{@attributes.inspect}>"
|
35
|
+
end
|
20
36
|
end
|
21
37
|
|
38
|
+
# <tt>find_*</tt> methods on <tt>Folder::BaseFolderId</tt> return a +FindResult+
|
22
39
|
class FindResult
|
23
40
|
VIEW_ATTRS = [:includes_last_item_in_range,
|
24
41
|
:indexed_paging_offset,
|
@@ -27,6 +44,8 @@ module Rews
|
|
27
44
|
VIEW_ATTRS.each do |attr|
|
28
45
|
attr_reader attr
|
29
46
|
end
|
47
|
+
|
48
|
+
# the +result+ of the +find_*+ call
|
30
49
|
attr_reader :result
|
31
50
|
|
32
51
|
def initialize(view, &proc)
|
@@ -36,19 +55,28 @@ module Rews
|
|
36
55
|
@result = proc.call(view) if proc
|
37
56
|
end
|
38
57
|
|
58
|
+
# count of items in the +result+
|
39
59
|
def length
|
40
60
|
result.length
|
41
61
|
end
|
42
62
|
|
63
|
+
# alias for +length+
|
43
64
|
def size
|
44
65
|
result.size
|
45
66
|
end
|
46
67
|
|
68
|
+
# access an element from +result+
|
47
69
|
def [](key)
|
48
70
|
result[key]
|
49
71
|
end
|
72
|
+
|
73
|
+
def inspect
|
74
|
+
attrs = VIEW_ATTRS.map{|attr| "@#{attr}=#{self.send(attr)}"}.join(", ")
|
75
|
+
"#<#{self.class} #{attrs}, @result=#{@result.inspect}>"
|
76
|
+
end
|
50
77
|
end
|
51
78
|
|
79
|
+
# Identifies a Folder
|
52
80
|
class BaseFolderId
|
53
81
|
include Util
|
54
82
|
|
@@ -63,6 +91,7 @@ module Rews
|
|
63
91
|
:indexed_page_folder_view=>View::INDEXED_PAGE_VIEW_OPTS,
|
64
92
|
:folder_shape=>Shape::FOLDER_SHAPE_OPTS}
|
65
93
|
|
94
|
+
# find <tt>Folder::Folder</tt>s within a <tt>Folder::Folder</tt>
|
66
95
|
def find_folder(opts={})
|
67
96
|
opts = check_opts(FIND_FOLDER_OPTS, opts)
|
68
97
|
|
@@ -76,7 +105,7 @@ module Rews
|
|
76
105
|
xml << Restriction.new(opts[:restriction]).to_xml if opts[:restriction]
|
77
106
|
|
78
107
|
xml.wsdl :ParentFolderIds do
|
79
|
-
xml <<
|
108
|
+
xml << self.to_xml
|
80
109
|
end
|
81
110
|
soap.body = xml.target!
|
82
111
|
end
|
@@ -91,6 +120,7 @@ module Rews
|
|
91
120
|
end
|
92
121
|
end
|
93
122
|
|
123
|
+
# find <tt>Folder::FolderIds</tt>s within a <tt>Folder::FolderIds</tt>
|
94
124
|
def find_folder_id(opts={})
|
95
125
|
opts = check_opts(FIND_FOLDER_OPTS, opts)
|
96
126
|
|
@@ -108,7 +138,7 @@ module Rews
|
|
108
138
|
:indexed_page_item_view=>View::INDEXED_PAGE_VIEW_OPTS,
|
109
139
|
:item_shape=>Shape::ITEM_SHAPE_OPTS}
|
110
140
|
|
111
|
-
# find
|
141
|
+
# find <tt>Item::Item</tt>s in a folder
|
112
142
|
def find_item(opts={})
|
113
143
|
opts = check_opts(FIND_ITEM_OPTS, opts)
|
114
144
|
|
@@ -124,7 +154,7 @@ module Rews
|
|
124
154
|
xml << SortOrder.new(opts[:sort_order]).to_xml if opts[:sort_order]
|
125
155
|
|
126
156
|
xml.wsdl :ParentFolderIds do
|
127
|
-
xml <<
|
157
|
+
xml << self.to_xml
|
128
158
|
end
|
129
159
|
|
130
160
|
soap.body = xml.target!
|
@@ -136,6 +166,7 @@ module Rews
|
|
136
166
|
end
|
137
167
|
end
|
138
168
|
|
169
|
+
# find <tt>Item::ItemIds</tt>s in a folder
|
139
170
|
def find_item_id(opts={})
|
140
171
|
opts = check_opts(FIND_ITEM_OPTS, opts)
|
141
172
|
|
@@ -152,7 +183,9 @@ module Rews
|
|
152
183
|
:ignore_change_keys=>nil
|
153
184
|
}
|
154
185
|
|
155
|
-
#
|
186
|
+
# retrieve a bunch of <tt>Item::Item</tt>s in one API hit.
|
187
|
+
# takes a list of <tt>Item::ItemId</tt>s, or a list of <tt>Item::Item</tt>,
|
188
|
+
# or a <tt>Folder::FindResult</tt> and options to specify +Shape::ItemShape+
|
156
189
|
def get_item(message_ids, opts={})
|
157
190
|
opts = check_opts(GET_ITEM_OPTS, opts)
|
158
191
|
message_ids = message_ids.result if message_ids.is_a?(FindResult)
|
@@ -166,7 +199,8 @@ module Rews
|
|
166
199
|
xml << Shape::ItemShape.new(opts[:item_shape]||{}).to_xml
|
167
200
|
xml.wsdl :ItemIds do
|
168
201
|
message_ids.each do |mid|
|
169
|
-
|
202
|
+
mid = mid.item_id if mid.is_a?(Item::Item)
|
203
|
+
xml << mid.to_xml(opts[:ignore_change_keys])
|
170
204
|
end
|
171
205
|
end
|
172
206
|
|
@@ -181,6 +215,9 @@ module Rews
|
|
181
215
|
:ignore_change_keys=>false
|
182
216
|
}
|
183
217
|
|
218
|
+
# delete a bunch of Items in one API hit.
|
219
|
+
# takes a list of <tt>Item::ItemId</tt>s, or a list of <tt>Item::Item</tt>,
|
220
|
+
# or a <tt>Folder::FindResult</tt> and options to specify DeleteType
|
184
221
|
def delete_item(message_ids, opts={})
|
185
222
|
opts = check_opts(DELETE_ITEM_OPTS, opts)
|
186
223
|
message_ids = message_ids.result if message_ids.is_a?(FindResult)
|
@@ -193,7 +230,8 @@ module Rews
|
|
193
230
|
|
194
231
|
xml.wsdl :ItemIds do
|
195
232
|
message_ids.each do |mid|
|
196
|
-
|
233
|
+
mid = mid.item_id if mid.is_a?(Item::Item)
|
234
|
+
xml << mid.to_xml(opts[:ignore_change_keys])
|
197
235
|
end
|
198
236
|
end
|
199
237
|
|
@@ -204,8 +242,12 @@ module Rews
|
|
204
242
|
end
|
205
243
|
end
|
206
244
|
|
245
|
+
# identifies a regular (non-distinguished) Folder on an Exchange server
|
207
246
|
class VanillaFolderId < BaseFolderId
|
247
|
+
# the Id of the Folder
|
208
248
|
attr_reader :id
|
249
|
+
|
250
|
+
# +change_key+ identifies a specific version of the Folder
|
209
251
|
attr_reader :change_key
|
210
252
|
|
211
253
|
def initialize(client, folder_id)
|
@@ -215,30 +257,33 @@ module Rews
|
|
215
257
|
raise "no id" if !@id
|
216
258
|
end
|
217
259
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
"Id" => id.to_s}}}
|
232
|
-
end
|
260
|
+
def ==(other)
|
261
|
+
other.is_a?(VanillaFolderId) &&
|
262
|
+
@client == other.client &&
|
263
|
+
@id == other.id &&
|
264
|
+
@change_key == other.change_key
|
265
|
+
end
|
266
|
+
|
267
|
+
def to_xml
|
268
|
+
xml = Builder::XmlMarkup.new
|
269
|
+
attrs = {:Id=>id.to_s}
|
270
|
+
attrs[:ChangeKey] = change_key.to_s if change_key
|
271
|
+
xml.t :FolderId, attrs
|
272
|
+
xml.target!
|
233
273
|
end
|
234
274
|
|
235
275
|
def inspect
|
236
|
-
"
|
276
|
+
"#<#{self.class} @id=#{id}, @change_key=#{change_key}>"
|
237
277
|
end
|
238
278
|
end
|
239
279
|
|
280
|
+
# identifies a DistinguishedFolder in a mailbox on an Exchange server.
|
281
|
+
# the <tt>Client.distinguished_folder_id</tt> method returns <tt>DistinguishedFolderId</tt>s
|
240
282
|
class DistinguishedFolderId < BaseFolderId
|
283
|
+
# the Id of the DistinguishedFolder e.g. <tt>"inbox"</tt>
|
241
284
|
attr_reader :id
|
285
|
+
|
286
|
+
# the email address of the mailbox containing the DistinguishedFolder
|
242
287
|
attr_reader :mailbox_email
|
243
288
|
|
244
289
|
def initialize(client, id, mailbox_email=nil)
|
@@ -248,26 +293,27 @@ module Rews
|
|
248
293
|
raise "no id" if !@id
|
249
294
|
end
|
250
295
|
|
251
|
-
def
|
252
|
-
|
253
|
-
|
254
|
-
|
296
|
+
def ==(other)
|
297
|
+
other.is_a?(DistinguishedFolderId) &&
|
298
|
+
@client = other.client &&
|
299
|
+
@id = other.id &&
|
300
|
+
@mailbox_email = other.mailbox_email
|
255
301
|
end
|
256
302
|
|
257
|
-
def
|
258
|
-
|
303
|
+
def to_xml
|
304
|
+
xml = Builder::XmlMarkup.new
|
305
|
+
xml.t :DistinguishedFolderId, :Id=>id do
|
306
|
+
if mailbox_email
|
307
|
+
xml.t :Mailbox do
|
308
|
+
xml.t :EmailAddress, mailbox_email
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
xml.target!
|
259
313
|
end
|
260
314
|
|
261
|
-
|
262
|
-
|
263
|
-
def mailbox_xml_hash
|
264
|
-
if mailbox_email
|
265
|
-
{
|
266
|
-
"t:Mailbox"=>{
|
267
|
-
"t:EmailAddress"=>mailbox_email}}
|
268
|
-
else
|
269
|
-
""
|
270
|
-
end
|
315
|
+
def inspect
|
316
|
+
"#<#{self.class} @id=#{id}, @mailbox_email=#{mailbox_email}>"
|
271
317
|
end
|
272
318
|
end
|
273
319
|
end
|
data/lib/rews/item.rb
CHANGED
@@ -20,6 +20,7 @@ module Rews
|
|
20
20
|
end.flatten
|
21
21
|
end
|
22
22
|
|
23
|
+
# represents an Item from a mailbox on an Exchange server
|
23
24
|
class Item
|
24
25
|
attr_reader :client
|
25
26
|
attr_reader :item_id
|
@@ -27,25 +28,45 @@ module Rews
|
|
27
28
|
attr_reader :attributes
|
28
29
|
|
29
30
|
def initialize(client, item_class, attributes)
|
31
|
+
@client = client
|
30
32
|
@item_id = ItemId.new(client, attributes[:item_id])
|
31
33
|
@item_class = item_class
|
32
34
|
@attributes = attributes
|
33
35
|
end
|
34
36
|
|
37
|
+
def ==(other)
|
38
|
+
other.is_a?(Item) &&
|
39
|
+
@client == other.client &&
|
40
|
+
@item_id == other.item_id &&
|
41
|
+
@item_class == other.item_class &&
|
42
|
+
@attributes == other.attributes
|
43
|
+
end
|
44
|
+
|
45
|
+
# access the Item attributes
|
35
46
|
def [](key)
|
36
47
|
@attributes[key]
|
37
48
|
end
|
38
|
-
|
49
|
+
|
50
|
+
# names of the Item attributes
|
39
51
|
def keys
|
40
52
|
@attributes.keys
|
41
53
|
end
|
54
|
+
|
55
|
+
def inspect
|
56
|
+
"#<#{self.class} @item_class=#{@item_class}, @item_id=#{@folder_id.inspect}, @attributes=#{@attributes.inspect}>"
|
57
|
+
end
|
42
58
|
end
|
43
59
|
|
60
|
+
# identifies an Item
|
44
61
|
class ItemId
|
45
62
|
include Util
|
46
63
|
|
47
64
|
attr_reader :client
|
65
|
+
|
66
|
+
# the +Id+ of the Item
|
48
67
|
attr_reader :id
|
68
|
+
|
69
|
+
# the version of the Item
|
49
70
|
attr_reader :change_key
|
50
71
|
|
51
72
|
def initialize(client, item_id)
|
@@ -55,11 +76,18 @@ module Rews
|
|
55
76
|
raise "no id" if !@id
|
56
77
|
end
|
57
78
|
|
79
|
+
def ==(other)
|
80
|
+
@client == other.client &&
|
81
|
+
@id == other.id &&
|
82
|
+
@change_key == other.change_key
|
83
|
+
end
|
84
|
+
|
58
85
|
GET_ITEM_OPTS = {
|
59
86
|
:item_shape=>Shape::ITEM_SHAPE_OPTS,
|
60
87
|
:ignore_change_keys=>nil
|
61
88
|
}
|
62
89
|
|
90
|
+
# get the <tt>Item::Item</tt> identified by this <tt>Item::ItemId</tt>
|
63
91
|
def get_item(opts={})
|
64
92
|
opts = check_opts(GET_ITEM_OPTS, opts)
|
65
93
|
r = with_error_check(client, :get_item_response,:response_messages,:get_item_response_message) do
|
@@ -70,7 +98,7 @@ module Rews
|
|
70
98
|
|
71
99
|
xml << Shape::ItemShape.new(opts[:item_shape]||{}).to_xml
|
72
100
|
xml.wsdl :ItemIds do
|
73
|
-
xml <<
|
101
|
+
xml << self.to_xml(opts[:ignore_change_keys])
|
74
102
|
end
|
75
103
|
|
76
104
|
soap.body = xml.target!
|
@@ -84,6 +112,7 @@ module Rews
|
|
84
112
|
:ignore_change_keys=>false
|
85
113
|
}
|
86
114
|
|
115
|
+
# delete the Item from the server
|
87
116
|
def delete_item(opts={})
|
88
117
|
opts = check_opts(DELETE_ITEM_OPTS, opts)
|
89
118
|
r = with_error_check(client, :delete_item_response, :response_messages, :delete_item_response_message) do
|
@@ -93,7 +122,7 @@ module Rews
|
|
93
122
|
xml = Builder::XmlMarkup.new
|
94
123
|
|
95
124
|
xml.wsdl :ItemIds do
|
96
|
-
xml <<
|
125
|
+
xml << self.to_xml(opts[:ignore_change_keys])
|
97
126
|
end
|
98
127
|
|
99
128
|
soap.body = xml.target!
|
@@ -102,25 +131,16 @@ module Rews
|
|
102
131
|
true
|
103
132
|
end
|
104
133
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
"Id" => id.to_s,
|
112
|
-
"ChangeKey" => change_key.to_s}}}
|
113
|
-
else
|
114
|
-
{
|
115
|
-
"t:ItemId"=>"",
|
116
|
-
:attributes! => {
|
117
|
-
"t:ItemId" => {
|
118
|
-
"Id" => id.to_s}}}
|
119
|
-
end
|
134
|
+
def to_xml(ignore_change_key=false)
|
135
|
+
xml = Builder::XmlMarkup.new
|
136
|
+
attrs = {:Id=>id.to_s}
|
137
|
+
attrs[:ChangeKey] = change_key.to_s if change_key && !ignore_change_key
|
138
|
+
xml.t :ItemId, attrs
|
139
|
+
xml.target!
|
120
140
|
end
|
121
141
|
|
122
142
|
def inspect
|
123
|
-
"
|
143
|
+
"#<#{self.class} @id=#{id}, @change_key=#{change_key}>"
|
124
144
|
end
|
125
145
|
end
|
126
146
|
end
|
data/lib/rews/restriction.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
# takes restrictions written in Ruby s-expressions and
|
2
|
-
# outputs Exchange Web Services Restriction XML
|
3
|
-
#
|
4
|
-
#
|
5
1
|
module Rews
|
2
|
+
# models Restrictions for <tt>find_*</tt> operations
|
3
|
+
# on <tt>Folder::BaseFolderId</tt>
|
4
|
+
#
|
5
|
+
# takes restrictions written in Ruby s-expressions and
|
6
|
+
# outputs Exchange Web Services Restriction XML. e.g.
|
7
|
+
#
|
8
|
+
# <tt>[[:and, [:==, "item:Subject", "hello"], [:>=, "item:DateTimeSent", DateTime.parse("2011-03-16T15:57:37+00:00")]]</tt>
|
6
9
|
class Restriction
|
7
10
|
|
8
11
|
attr_reader :expr
|
@@ -12,7 +15,7 @@ module Rews
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def inspect
|
15
|
-
"
|
18
|
+
"#<#{self.class} @expr=#{@expr.inspect}>"
|
16
19
|
end
|
17
20
|
|
18
21
|
def to_xml
|
@@ -81,7 +84,9 @@ module Rews
|
|
81
84
|
}
|
82
85
|
def write_logical(xml, expr)
|
83
86
|
xml.t LOGICAL_OPS[expr[0]] do
|
84
|
-
|
87
|
+
expr[1..-1].each do |clause|
|
88
|
+
Xml::write_expr(xml, clause)
|
89
|
+
end
|
85
90
|
end
|
86
91
|
end
|
87
92
|
end
|
data/lib/rews/shape.rb
CHANGED
@@ -24,9 +24,15 @@ module Rews
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
# models ItemShape and FolderShape used in <tt>Folder::BaseFolderId.find_*</tt> and
|
28
|
+
# <tt>Folder::BaseFolderId.get_*</tt> methods
|
27
29
|
class Base
|
28
30
|
include Util
|
29
31
|
attr_reader :shape
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<#{self.class} @shape=#{@shape}>"
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
ITEM_SHAPE_OPTS = {
|
@@ -35,6 +41,8 @@ module Rews
|
|
35
41
|
:additional_properties=>nil
|
36
42
|
}
|
37
43
|
|
44
|
+
# models ItemShape used in <tt>Folder::BaseFolderId.find_item</tt> and
|
45
|
+
# <tt>Folder::BaseFolderId.get_item</tt> methods
|
38
46
|
class ItemShape < Base
|
39
47
|
def initialize(shape)
|
40
48
|
@shape = check_opts(ITEM_SHAPE_OPTS, shape)
|
@@ -54,6 +62,7 @@ module Rews
|
|
54
62
|
:additional_properties=>nil
|
55
63
|
}
|
56
64
|
|
65
|
+
# models +FolderShape+ used in <tt>Folder::BaseFolderId.find_folder</tt> method
|
57
66
|
class FolderShape < Base
|
58
67
|
def initialize(shape)
|
59
68
|
@shape = check_opts(FOLDER_SHAPE_OPTS, shape)
|
data/lib/rews/sort_order.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
# takes sort_orders written in Ruby s-expressions and
|
2
|
-
# outputs EWS SortOrder XML
|
3
1
|
module Rews
|
2
|
+
# models SortOrder used in <tt>Folder::BaseFolderId.find_*</tt> methods
|
3
|
+
#
|
4
|
+
# takes sort_orders written in Ruby s-expressions and
|
5
|
+
# outputs EWS SortOrder XML e.g.
|
6
|
+
#
|
7
|
+
# <tt>[["item:DateTimeReceived", "Ascending"], ["item:Size", "Descending"]]</tt>
|
4
8
|
class SortOrder
|
5
9
|
attr_reader :expr
|
6
10
|
|
@@ -9,7 +13,7 @@ module Rews
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def inspect
|
12
|
-
"
|
16
|
+
"#<#{self.class} @expr=#{@expr.inspect}>"
|
13
17
|
end
|
14
18
|
|
15
19
|
def to_xml
|
data/lib/rews/util.rb
CHANGED
@@ -6,10 +6,10 @@ module Rews
|
|
6
6
|
|
7
7
|
# validates an options hash against a constraints hash
|
8
8
|
# in the constraints hash :
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
9
|
+
# * keys ending in ! indicate option is required
|
10
|
+
# * keys not ending in ! indicate option is not required
|
11
|
+
# * non-nil values provide defaults
|
12
|
+
# * hash values provide constraints for sub-hashes
|
13
13
|
def check_opts(constraints, opts={}, prefix=nil)
|
14
14
|
required_keys = Hash[constraints.keys.select{|k| k.to_s[-1..-1] == '!'}.map{|k| [strip_bang(k),k]}]
|
15
15
|
optional_keys = constraints.keys.select{|k| k.to_s[-1..-1] != '!'}
|
@@ -30,10 +30,11 @@ module Rews
|
|
30
30
|
raise "required options not given: #{required_keys.keys.map{|k| [prefix,k].compact.join('.')}.join(", ")}" if required_keys.size>0
|
31
31
|
|
32
32
|
# defaults
|
33
|
-
optional_keys.each{|k| opts[k] = constraints[k] if !constraints[k].is_a?(Hash)}
|
33
|
+
optional_keys.each{|k| opts[k] = constraints[k] if constraints[k] && !constraints[k].is_a?(Hash)}
|
34
34
|
opts
|
35
35
|
end
|
36
36
|
|
37
|
+
# strip a ! from the end of a +String+ or +Symbol+
|
37
38
|
def strip_bang(k)
|
38
39
|
if k.is_a? Symbol
|
39
40
|
k.to_s[0...-1].to_sym
|
@@ -42,14 +43,19 @@ module Rews
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
# camel-case a +String+
|
45
47
|
def camelize(s)
|
46
48
|
s.split('_').map(&:capitalize).join
|
47
49
|
end
|
48
50
|
|
51
|
+
# camel-case the keys of a +Hash+
|
49
52
|
def camel_keys(h)
|
50
53
|
Hash[h.map{|k,v| [camelize(k.to_s), v]}]
|
51
54
|
end
|
52
55
|
|
56
|
+
# check the response codes of an Exchange Web Services request.
|
57
|
+
# the supplied block makes a SOAP request, and the response is parsed
|
58
|
+
# out and checked
|
53
59
|
def with_error_check(client, *response_msg_keys)
|
54
60
|
raise "no block" if !block_given?
|
55
61
|
|
@@ -69,6 +75,7 @@ module Rews
|
|
69
75
|
statuses
|
70
76
|
end
|
71
77
|
|
78
|
+
# check the status of the response of a single part of a multi-part request
|
72
79
|
def single_error_check(client, status)
|
73
80
|
begin
|
74
81
|
response_class = status[:response_class]
|
@@ -77,9 +84,9 @@ module Rews
|
|
77
84
|
end
|
78
85
|
|
79
86
|
if status[:response_class] == "Error"
|
80
|
-
return "
|
87
|
+
return "#{status[:response_code]} - #{status[:message_text]}"
|
81
88
|
elsif status[:response_class] == "Warning"
|
82
|
-
client.log{|logger| logger.warn("#{status[:message_text]}")}
|
89
|
+
client.log{|logger| logger.warn("#{status[:response_code]} - #{status[:message_text]}")}
|
83
90
|
end
|
84
91
|
end
|
85
92
|
end
|
data/lib/rews/view.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module Rews
|
2
|
+
# models IndexedPageItemView and IndexedPageFolderView definitions used by
|
3
|
+
# <tt>Folder::BaseFolderId.find_*</tt> methods
|
2
4
|
module View
|
3
5
|
module Xml
|
4
6
|
module_function
|
@@ -16,10 +18,15 @@ module Rews
|
|
16
18
|
include Util
|
17
19
|
|
18
20
|
attr_reader :view
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"#<#{self.class} @view=#{@view.inspect}>"
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
INDEXED_PAGE_VIEW_OPTS = {:max_entries_returned=>nil, :offset=>0, :base_point=>:Beginning}
|
22
28
|
|
29
|
+
# models the IndexedPageItemView used in <tt>Folder::BaseFolderId.find_item</tt> method
|
23
30
|
class IndexedPageItemView < Base
|
24
31
|
def initialize(view)
|
25
32
|
@view = check_opts(INDEXED_PAGE_VIEW_OPTS, view)
|
@@ -30,6 +37,7 @@ module Rews
|
|
30
37
|
end
|
31
38
|
end
|
32
39
|
|
40
|
+
# models the IndexedPageFolderView used in <tt>Folder::BaseFolderId.find_folder</tt> methods
|
33
41
|
class IndexedPageFolderView < Base
|
34
42
|
def initialize(view)
|
35
43
|
@view = check_opts(INDEXED_PAGE_VIEW_OPTS, view)
|