exchanger 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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