exchanger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +53 -0
  3. data/lib/exchanger.rb +79 -0
  4. data/lib/exchanger/attributes.rb +61 -0
  5. data/lib/exchanger/boolean.rb +4 -0
  6. data/lib/exchanger/client.rb +19 -0
  7. data/lib/exchanger/config.rb +32 -0
  8. data/lib/exchanger/dirty.rb +239 -0
  9. data/lib/exchanger/element.rb +161 -0
  10. data/lib/exchanger/elements/attendee.rb +10 -0
  11. data/lib/exchanger/elements/base_folder.rb +61 -0
  12. data/lib/exchanger/elements/calendar_folder.rb +11 -0
  13. data/lib/exchanger/elements/calendar_item.rb +59 -0
  14. data/lib/exchanger/elements/complete_name.rb +16 -0
  15. data/lib/exchanger/elements/contact.rb +49 -0
  16. data/lib/exchanger/elements/contacts_folder.rb +17 -0
  17. data/lib/exchanger/elements/distribution_list.rb +8 -0
  18. data/lib/exchanger/elements/email_address.rb +16 -0
  19. data/lib/exchanger/elements/entry.rb +11 -0
  20. data/lib/exchanger/elements/folder.rb +9 -0
  21. data/lib/exchanger/elements/identifier.rb +7 -0
  22. data/lib/exchanger/elements/im_address.rb +20 -0
  23. data/lib/exchanger/elements/item.rb +86 -0
  24. data/lib/exchanger/elements/mailbox.rb +34 -0
  25. data/lib/exchanger/elements/meeting_cancellation.rb +4 -0
  26. data/lib/exchanger/elements/meeting_message.rb +16 -0
  27. data/lib/exchanger/elements/meeting_request.rb +6 -0
  28. data/lib/exchanger/elements/meeting_response.rb +4 -0
  29. data/lib/exchanger/elements/message.rb +24 -0
  30. data/lib/exchanger/elements/phone_number.rb +13 -0
  31. data/lib/exchanger/elements/physical_address.rb +15 -0
  32. data/lib/exchanger/elements/search_folder.rb +5 -0
  33. data/lib/exchanger/elements/single_recipient.rb +6 -0
  34. data/lib/exchanger/elements/task.rb +5 -0
  35. data/lib/exchanger/elements/tasks_folder.rb +4 -0
  36. data/lib/exchanger/field.rb +139 -0
  37. data/lib/exchanger/operation.rb +110 -0
  38. data/lib/exchanger/operations/create_item.rb +64 -0
  39. data/lib/exchanger/operations/expand_dl.rb +42 -0
  40. data/lib/exchanger/operations/find_folder.rb +55 -0
  41. data/lib/exchanger/operations/find_item.rb +54 -0
  42. data/lib/exchanger/operations/get_folder.rb +55 -0
  43. data/lib/exchanger/operations/get_item.rb +44 -0
  44. data/lib/exchanger/operations/resolve_names.rb +43 -0
  45. data/lib/exchanger/operations/update_item.rb +43 -0
  46. data/lib/exchanger/persistence.rb +27 -0
  47. data/spec/calendar_item_spec.rb +26 -0
  48. data/spec/client_spec.rb +11 -0
  49. data/spec/contact_spec.rb +68 -0
  50. data/spec/element_spec.rb +4 -0
  51. data/spec/field_spec.rb +118 -0
  52. data/spec/folder_spec.rb +13 -0
  53. data/spec/mailbox_spec.rb +9 -0
  54. data/spec/spec_helper.rb +6 -0
  55. metadata +208 -0
@@ -0,0 +1,64 @@
1
+ module Exchanger
2
+ # The CreateItem operation creates items in the Exchanger store.
3
+ #
4
+ # You can use the CreateItem operation to create the following:
5
+ # * Calendar items
6
+ # * E-mail messages
7
+ # * Meeting requests
8
+ # * Tasks
9
+ # * Contacts
10
+ #
11
+ # http://msdn.microsoft.com/en-us/library/aa563797.aspx
12
+ class CreateItem < Operation
13
+ class Request < Operation::Request
14
+ attr_accessor :folder_id, :email_address, :items
15
+
16
+ # Reset request options to defaults.
17
+ def reset
18
+ @folder_id = :contacts
19
+ @email_address = nil
20
+ @items = []
21
+ end
22
+
23
+ def to_xml
24
+ Nokogiri::XML::Builder.new do |xml|
25
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"], "xmlns:t" => NS["t"], "xmlns:xsi" => NS["xsi"], "xmlns:xsd" => NS["xsd"]) do
26
+ xml.send("soap:Body") do
27
+ xml.CreateItem("xmlns" => NS["m"]) do
28
+ xml.SavedItemFolderId do
29
+ if folder_id.is_a?(Symbol)
30
+ xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
31
+ if email_address
32
+ xml.send("t:Mailbox") do
33
+ xml.send("t:EmailAddress", email_address)
34
+ end
35
+ end
36
+ end
37
+ else
38
+ xml.send("t:FolderId", "Id" => folder_id)
39
+ end
40
+ end
41
+ xml.Items do
42
+ items.each do |item|
43
+ item_xml = item.to_xml
44
+ item_xml.add_namespace_definition("t", NS["t"])
45
+ item_xml.namespace = item_xml.namespace_definitions[0]
46
+ xml << item_xml.to_s
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class Response < Operation::Response
57
+ def item_ids
58
+ to_xml.xpath(".//t:ItemId", NS).map do |node|
59
+ Identifier.new_from_xml(node)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ module Exchanger
2
+ # The ExpandDL operation exposes the full membership of distribution lists.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa494152.aspx
5
+ class ExpandDL < Operation
6
+ class Request < Operation::Request
7
+ attr_accessor :mailbox
8
+
9
+ # Reset request options to defaults.
10
+ def reset
11
+ @mailbox = nil
12
+ end
13
+
14
+ def to_xml
15
+ Nokogiri::XML::Builder.new do |xml|
16
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
17
+ xml.send("soap:Body") do
18
+ xml.ExpandDL("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
19
+ xml.Mailbox do
20
+ if mailbox.item_id
21
+ xml.send("t:ItemId", "Id" => mailbox.item_id.id, "ChangeKey" => mailbox.item_id.change_key)
22
+ else
23
+ xml.send("t:EmailAddress", mailbox.email_address)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ class Response < Operation::Response
34
+ def mailboxes
35
+ to_xml.xpath(".//t:Mailbox", NS).map do |node|
36
+ item_klass = Exchanger.const_get(node.name)
37
+ item_klass.new_from_xml(node)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ module Exchanger
2
+ # The FindFolder operation uses Exchanger Web Services to find subfolders of
3
+ # an identified folder and returns a set of properties that describe the set of subfolders.
4
+ #
5
+ # http://msdn.microsoft.com/en-us/library/aa563918.aspx
6
+ class FindFolder < Operation
7
+ class Request < Operation::Request
8
+ attr_accessor :parent_folder_id, :base_shape, :email_address, :traversal
9
+
10
+ # Reset request options to defaults.
11
+ def reset
12
+ @parent_folder_id = nil
13
+ @traversal = :shallow
14
+ @base_shape = :all_properties
15
+ @email_address = nil
16
+ end
17
+
18
+ def to_xml
19
+ Nokogiri::XML::Builder.new do |xml|
20
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
21
+ xml.send("soap:Body") do
22
+ xml.FindFolder("xmlns" => NS["m"], "xmlns:t" => NS["t"], "Traversal" => traversal.to_s.camelize) do
23
+ xml.FolderShape do
24
+ xml.send "t:BaseShape", base_shape.to_s.camelize
25
+ end
26
+ xml.ParentFolderIds do
27
+ if parent_folder_id.is_a?(Symbol)
28
+ xml.send("t:DistinguishedFolderId", "Id" => parent_folder_id) do
29
+ if email_address
30
+ xml.send("t:Mailbox") do
31
+ xml.send("t:EmailAddress", email_address)
32
+ end
33
+ end
34
+ end
35
+ else
36
+ xml.send("t:FolderId", "Id" => parent_folder_id)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ class Response < Operation::Response
47
+ def folders
48
+ to_xml.xpath(".//t:Folders", NS).children.map do |node|
49
+ folder_klass = Exchanger.const_get(node.name)
50
+ folder_klass.new_from_xml(node)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,54 @@
1
+ module Exchanger
2
+ # The FindItem operation identifies items that are located in a specified folder.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa566107.aspx
5
+ class FindItem < Operation
6
+ class Request < Operation::Request
7
+ attr_accessor :folder_id, :traversal, :base_shape, :email_address
8
+
9
+ # Reset request options to defaults.
10
+ def reset
11
+ @folder_id = :contacts
12
+ @traversal = :shallow
13
+ @base_shape = :all_properties
14
+ @email_address = nil
15
+ end
16
+
17
+ def to_xml
18
+ Nokogiri::XML::Builder.new do |xml|
19
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
20
+ xml.send("soap:Body") do
21
+ xml.FindItem("xmlns" => NS["m"], "xmlns:t" => NS["t"], "Traversal" => traversal.to_s.camelize) do
22
+ xml.ItemShape do
23
+ xml.send "t:BaseShape", base_shape.to_s.camelize
24
+ end
25
+ xml.ParentFolderIds do
26
+ if folder_id.is_a?(Symbol)
27
+ xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
28
+ if email_address
29
+ xml.send("t:Mailbox") do
30
+ xml.send("t:EmailAddress", email_address)
31
+ end
32
+ end
33
+ end
34
+ else
35
+ xml.send("t:FolderId", "Id" => folder_id)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ class Response < Operation::Response
46
+ def items
47
+ to_xml.xpath(".//t:Items", NS).children.map do |node|
48
+ item_klass = Exchanger.const_get(node.name)
49
+ item_klass.new_from_xml(node)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ module Exchanger
2
+ # The GetFolder operation gets folders from the Exchanger store.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa580274.aspx
5
+ class GetFolder < Operation
6
+ class Request < Operation::Request
7
+ attr_accessor :folder_ids, :base_shape, :email_address
8
+
9
+ # Reset request options to defaults.
10
+ def reset
11
+ @folder_ids = []
12
+ @base_shape = :default
13
+ @email_address = nil
14
+ end
15
+
16
+ def to_xml
17
+ Nokogiri::XML::Builder.new do |xml|
18
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
19
+ xml.send("soap:Body") do
20
+ xml.GetFolder("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
21
+ xml.FolderShape do
22
+ xml.send "t:BaseShape", base_shape.to_s.camelize
23
+ end
24
+ xml.FolderIds do
25
+ folder_ids.each do |folder_id|
26
+ if folder_id.is_a?(Symbol)
27
+ xml.send("t:DistinguishedFolderId", "Id" => folder_id) do
28
+ if email_address
29
+ xml.send("t:Mailbox") do
30
+ xml.send("t:EmailAddress", email_address)
31
+ end
32
+ end
33
+ end
34
+ else
35
+ xml.send("t:FolderId", "Id" => folder_id)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ class Response < Operation::Response
47
+ def folders
48
+ to_xml.xpath(".//m:Folders", NS).children.map do |node|
49
+ folder_klass = Exchanger.const_get(node.name)
50
+ folder_klass.new_from_xml(node)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,44 @@
1
+ module Exchanger
2
+ # The GetItem operation gets items from the Exchanger store.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa565934.aspx
5
+ class GetItem < Operation
6
+ class Request < Operation::Request
7
+ attr_accessor :item_ids, :base_shape
8
+
9
+ # Reset request options to defaults.
10
+ def reset
11
+ @item_ids = []
12
+ @base_shape = :all_properties
13
+ end
14
+
15
+ def to_xml
16
+ Nokogiri::XML::Builder.new do |xml|
17
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
18
+ xml.send("soap:Body") do
19
+ xml.GetItem("xmlns" => NS["m"], "xmlns:t" => NS["t"]) do
20
+ xml.ItemShape do
21
+ xml.send "t:BaseShape", base_shape.to_s.camelize
22
+ end
23
+ xml.ItemIds do
24
+ item_ids.each do |item_id|
25
+ xml.send("t:ItemId", "Id" => item_id)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ class Response < Operation::Response
36
+ def items
37
+ to_xml.xpath(".//m:Items", NS).children.map do |node|
38
+ item_klass = Exchanger.const_get(node.name)
39
+ item_klass.new_from_xml(node)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ module Exchanger
2
+ # The ResolveNames operation resolves ambiguous e-mail addresses and display names.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa563518.aspx
5
+ class ResolveNames < Operation
6
+ class Request < Operation::Request
7
+ attr_accessor :name
8
+
9
+ # Reset request options to defaults.
10
+ def reset
11
+ @name = nil
12
+ end
13
+
14
+ def to_xml
15
+ Nokogiri::XML::Builder.new do |xml|
16
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"]) do
17
+ xml.send("soap:Body") do
18
+ xml.ResolveNames("xmlns" => NS["m"], "xmlns:t" => NS["t"], "ReturnFullContactData" => "true") do
19
+ xml.UnresolvedEntry name
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ class Response < Operation::Response
28
+ def mailboxes
29
+ to_xml.xpath(".//t:Mailbox", NS).map do |node|
30
+ item_klass = Exchanger.const_get(node.name)
31
+ item_klass.new_from_xml(node)
32
+ end
33
+ end
34
+
35
+ def contacts
36
+ to_xml.xpath(".//t:Contact", NS).map do |node|
37
+ item_klass = Exchanger.const_get(node.name)
38
+ item_klass.new_from_xml(node)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ module Exchanger
2
+ # The UpdateItem operation is used to modify the properties of an existing item in the Exchanger store.
3
+ #
4
+ # http://msdn.microsoft.com/en-us/library/aa581084.aspx
5
+ # http://msdn.microsoft.com/en-us/library/aa579673.aspx
6
+ class UpdateItem < Operation
7
+ class Request < Operation::Request
8
+ attr_accessor :items
9
+
10
+ # Reset request options to defaults.
11
+ def reset
12
+ @items = []
13
+ end
14
+
15
+ def to_xml
16
+ Nokogiri::XML::Builder.new do |xml|
17
+ xml.send("soap:Envelope", "xmlns:soap" => NS["soap"], "xmlns:t" => NS["t"], "xmlns:xsi" => NS["xsi"], "xmlns:xsd" => NS["xsd"]) do
18
+ xml.send("soap:Body") do
19
+ xml.UpdateItem("xmlns" => NS["m"], "ConflictResolution" => "AlwaysOverwrite") do
20
+ xml.ItemChanges do
21
+ items.each do |item|
22
+ item_change = item.to_xml_change
23
+ item_change.add_namespace_definition("t", NS["t"])
24
+ item_change.namespace = item_change.namespace_definitions[0]
25
+ xml << item_change.to_s
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ class Response < Operation::Response
36
+ def item_ids
37
+ to_xml.xpath(".//t:ItemId", NS).map do |node|
38
+ Identifier.new_from_xml(node)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ module Exchanger
2
+ module Persistence
3
+ def new_record?
4
+ not id
5
+ end
6
+
7
+ def save
8
+ if new_record?
9
+ create
10
+ else
11
+ update
12
+ end
13
+ end
14
+
15
+ # Reloads the +Element+ attributes from Exchanger.
16
+ def reload
17
+ if new_record?
18
+ false
19
+ else
20
+ reloaded_element = self.class.find(self.id)
21
+ @attributes = reloaded_element.attributes
22
+ reset_modifications
23
+ true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require "spec/spec_helper"
2
+
3
+ describe Exchanger::CalendarFolder do
4
+ before do
5
+ @folder = Exchanger::Folder.find(:calendar, "edgars.beigarts@tieto.com")
6
+ end
7
+
8
+ it "should return calendar folder" do
9
+ @folder.class.should == Exchanger::CalendarFolder
10
+ end
11
+
12
+ it "should have calendar items" do
13
+ @folder.items.size.should > 0
14
+ end
15
+ end
16
+
17
+ describe Exchanger::CalendarItem do
18
+ before do
19
+ @folder = Exchanger::Folder.find(:calendar, "edgars.beigarts@tieto.com")
20
+ @item = @folder.items.first
21
+ end
22
+
23
+ it "should have start time" do
24
+ @item.start.class.should == Time
25
+ end
26
+ end