viewpoint 0.1.8 → 0.1.9

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.1.9
@@ -24,6 +24,10 @@ module Viewpoint
24
24
  class EwsError < StandardError
25
25
  end
26
26
 
27
+ # Raise when authentication/authorization issues occur.
28
+ class EwsLoginError < StandardError
29
+ end
30
+
27
31
  # Raised when a user tries to query a folder subscription after the
28
32
  # subscription has timed out.
29
33
  class EwsSubscriptionTimeout < StandardError
@@ -22,27 +22,16 @@ module Viewpoint
22
22
  module EWS
23
23
  class CalendarFolder < GenericFolder
24
24
 
25
- # Find Calendar subfolders of the passed root folder. If no parameters are passed
26
- # this method will search from the Root folder.
27
- # @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
25
+ # Find folders of type Task
26
+ # @see GenericFolder.find_folders
27
+ # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
28
28
  # or a FolderId (String)
29
29
  # @param [String] traversal Shallow/Deep/SoftDeleted
30
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
31
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
30
32
  # @return [Array] Returns an Array of Folder or subclasses of Folder
31
- def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
32
- restr = {:restriction =>
33
- {:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Appointment'}}}}
34
- }
35
- resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
36
- if(resp.status == 'Success')
37
- folders = []
38
- resp.items.each do |f|
39
- f_type = f.keys.first.to_s.camel_case
40
- folders << (eval "#{f_type}.new(f[f.keys.first])")
41
- end
42
- return folders
43
- else
44
- raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
45
- end
33
+ def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default', folder_type = 'IPF.Appointment')
34
+ super(root, traversal, shape, folder_type)
46
35
  end
47
36
 
48
37
 
@@ -20,12 +20,48 @@
20
20
 
21
21
  module Viewpoint
22
22
  module EWS
23
+ # Represents a Contact Item in the Exchange datastore.
23
24
  class Contact < Item
24
25
 
26
+ # This is a class method that creates a new Contact in the Exchange Data Store.
27
+ # @param [Hash] item A Hash of values based on values found here:
28
+ # http://msdn.microsoft.com/en-us/library/aa581315.aspx
29
+ # @param [String, Symbol] folder_id The folder to create this item in. Either a
30
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
31
+ # @param [String] send_invites "SendToNone/SendOnlyToAll/SendToAllAndSaveCopy"
32
+ # See: http://msdn.microsoft.com/en-us/library/aa565209.aspx
33
+ # @example Typical Usage
34
+ # item = {
35
+ # :file_as => {:text => 'Dan Wanek'},
36
+ # :given_name => {:text => 'Dan Wanek'},
37
+ # :company_name => {:text => 'Test Company'},
38
+ # :email_addresses => [
39
+ # {:entry => {:key => 'EmailAddress1', :text => 'myemail@work.com'}},
40
+ # {:entry => {:key => 'EmailAddress2', :text => 'myemail@home.com'}}
41
+ # ],
42
+ # :physical_addresses => [
43
+ # {:entry => {:key => 'Business', :sub_elements => {:street => {:text => '6343 N Baltimore'}, :city => {:text => 'Bismarck'}, :state => {:text => 'ND'} }}}
44
+ # ],
45
+ # :phone_numbers => [
46
+ # {:entry => {:key => 'BusinessPhone', :text => '7012220000'}}
47
+ # ],
48
+ # :job_title => {:text => 'Systems Architect'}
49
+ # }
50
+ # @example Minimal Usage
51
+ def self.create_item_from_hash(item, folder_id = :contacts)
52
+ conn = Viewpoint::EWS::EWS.instance
53
+ resp = conn.ews.create_contact_item(folder_id, item)
54
+ if(resp.status == 'Success')
55
+ resp = resp.items.shift
56
+ self.new(resp[resp.keys.first])
57
+ else
58
+ raise EwsError, "Could not create Contact. #{resp.code}: #{resp.message}"
59
+ end
60
+ end
61
+
62
+
63
+
25
64
  # Create a Contact in the Exchange Data Store
26
- #
27
- # @param [String] subject The task subject
28
- # @param [String] body The task body
29
65
  def self.add_contact()
30
66
  item = {}
31
67
 
@@ -22,6 +22,19 @@ module Viewpoint
22
22
  module EWS
23
23
  class ContactsFolder < GenericFolder
24
24
 
25
+ # Find folders of type Contact
26
+ # @see GenericFolder.find_folders
27
+ # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
28
+ # or a FolderId (String)
29
+ # @param [String] traversal Shallow/Deep/SoftDeleted
30
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
31
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
32
+ # @return [Array] Returns an Array of Folder or subclasses of Folder
33
+ def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default', folder_type = 'IPF.Contact')
34
+ super(root, traversal, shape, folder_type)
35
+ end
36
+
37
+
25
38
  # initialize with an item of CalendarFolderType
26
39
  def initialize(folder)
27
40
  super(folder)
@@ -24,27 +24,16 @@ module Viewpoint
24
24
  # This is the type of folder that mail messages will be found in.
25
25
  class Folder < GenericFolder
26
26
 
27
- # Find Message subfolders of the passed root folder. If no parameters are passed
28
- # this method will search from the Root folder.
29
- # @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
27
+ # Find folders of type Folder (message folders)
28
+ # @see GenericFolder.find_folders
29
+ # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
30
30
  # or a FolderId (String)
31
31
  # @param [String] traversal Shallow/Deep/SoftDeleted
32
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
33
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
32
34
  # @return [Array] Returns an Array of Folder or subclasses of Folder
33
- def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
34
- restr = {:restriction =>
35
- {:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Note'}}}}
36
- }
37
- resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
38
- if(resp.status == 'Success')
39
- folders = []
40
- resp.items.each do |f|
41
- f_type = f.keys.first.to_s.camel_case
42
- folders << (eval "#{f_type}.new(f[f.keys.first])")
43
- end
44
- return folders
45
- else
46
- raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
47
- end
35
+ def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default', folder_type = 'IPF.Note')
36
+ super(root, traversal, shape, folder_type)
48
37
  end
49
38
 
50
39
 
@@ -62,9 +62,19 @@ module Viewpoint
62
62
  # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
63
63
  # or a FolderId (String)
64
64
  # @param [String] traversal Shallow/Deep/SoftDeleted
65
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
66
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
65
67
  # @return [Array] Returns an Array of Folder or subclasses of Folder
66
- def self.find_folders(root = :msgfolderroot, traversal = 'Shallow', shape = 'Default')
67
- resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape} )
68
+ def self.find_folders(root = :msgfolderroot, traversal = 'Shallow', shape = 'Default', folder_type = nil)
69
+ if( folder_type.nil? )
70
+ resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape} )
71
+ else
72
+ restr = {:restriction =>
73
+ {:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => folder_type}}}}
74
+ }
75
+ resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
76
+ end
77
+
68
78
  if(resp.status == 'Success')
69
79
  folders = []
70
80
  resp.items.each do |f|
@@ -205,7 +215,9 @@ module Viewpoint
205
215
 
206
216
  # Find Items
207
217
  def find_items(opts = {})
208
- resp = (Viewpoint::EWS::EWS.instance).ews.find_item([@folder_id], 'Shallow', {:base_shape => 'Default'}, opts)
218
+ item_shape = {:base_shape => 'Default'}
219
+ item_shape[:additional_properties] = {:field_uRI => ['item:ParentFolderId']}
220
+ resp = (Viewpoint::EWS::EWS.instance).ews.find_item([@folder_id], 'Shallow', item_shape, opts)
209
221
  if(resp.status == 'Success')
210
222
  parms = resp.items.shift
211
223
  items = []
@@ -288,7 +300,8 @@ module Viewpoint
288
300
  # @param [String] change_key specify an optional change_key if you want to
289
301
  # make sure you are fetching a specific version of the object.
290
302
  def get_item(item_id, change_key = nil)
291
- resp = (Viewpoint::EWS::EWS.instance).ews.get_item([item_id])
303
+ item_shape = {:base_shape => 'Default', :additional_properties => {:field_uRI => ['item:ParentFolderId']}}
304
+ resp = (Viewpoint::EWS::EWS.instance).ews.get_item([item_id], item_shape)
292
305
  if(resp.status == 'Success')
293
306
  item = resp.items.shift
294
307
  type = item.keys.first
@@ -36,7 +36,8 @@ module Viewpoint
36
36
  conn = Viewpoint::EWS::EWS.instance
37
37
  resp = conn.ews.get_item([item_id])
38
38
  resp = resp.items.shift
39
- self.new(resp[resp.keys.first])
39
+ resp_type = resp.keys.first
40
+ eval "#{resp_type.to_s.camel_case}.new(resp[resp_type])"
40
41
  end
41
42
 
42
43
  # Add attachments to the passed in ParentId
@@ -200,6 +201,14 @@ module Viewpoint
200
201
  (resp.status == 'Success') || (raise EwsError, "Could not recycle message. #{resp.code}: #{resp.message}")
201
202
  end
202
203
 
204
+ # Get the parent folder of this item
205
+ # @return [GenericFolder] returns a GenericFolder of subclass of that type.
206
+ def parent_folder
207
+ #deepen!
208
+ GenericFolder.get_folder @parent_folder_id
209
+ end
210
+
211
+
203
212
  private
204
213
 
205
214
  # @todo Handle:
@@ -0,0 +1,28 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ # Meeting cancellations have the exact same elements as a Meeting Message
24
+ # so MeetingCancellation is just a subclass of that.
25
+ class MeetingCancellation < MeetingMessage
26
+ end # MeetingCancellation
27
+ end # EWS
28
+ end # Viewpoint
@@ -0,0 +1,30 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ class MeetingMessage < Item
24
+
25
+ def initialize(ews_item)
26
+ super(ews_item)
27
+ end
28
+ end # MeetingMessage
29
+ end # EWS
30
+ end # Viewpoint
@@ -0,0 +1,41 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ class MeetingRequest < Item
24
+
25
+
26
+ private
27
+
28
+ def init_methods
29
+ super()
30
+ define_str_var :conversation_index, :conversation_topic, :internet_message_id, :references
31
+ define_mbox_users :to_recipients, :cc_recipients, :bcc_recipients, :reply_to, :required_attendees, :optional_attendees
32
+ define_mbox_user :from, :sender, :received_by, :received_representing, :organizer
33
+ define_bool_var :is_read, :is_read_receipt_requested, :is_response_requested, :is_delivery_receipt_requested, :is_draft, :is_from_me
34
+ define_bool_var :is_all_day_event, :is_cancelled, :is_delegated, :is_meeting, :is_out_of_date, :is_recurring, :is_resend
35
+ define_bool_var :is_submitted, :is_unmodified, :allow_new_time_proposal
36
+ define_int_var :adjacent_meeting_count, :appointment_sequence_number, :appointment_state, :conflicting_meeting_count
37
+ define_datetime_var :start, :end
38
+ end
39
+ end # MeetingRequest
40
+ end # EWS
41
+ end # Viewpoint
@@ -0,0 +1,26 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Viewpoint
22
+ module EWS
23
+ class MeetingResponse < Item
24
+ end # MeetingResponse
25
+ end # EWS
26
+ end # Viewpoint
@@ -23,6 +23,20 @@ module Viewpoint
23
23
  # This class represents a SearchFolderType object in the Exchange Data store.
24
24
  class SearchFolder < GenericFolder
25
25
 
26
+ # Find folders of type SearchFolder
27
+ # @see GenericFolder.find_folders
28
+ # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
29
+ # or a FolderId (String). SearchFolders must be created under the :searchfolders distinguished
30
+ # id so we might as well only search from there.
31
+ # @param [String] traversal Shallow/Deep/SoftDeleted
32
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
33
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
34
+ # @return [Array] Returns an Array of Folder or subclasses of Folder
35
+ def self.find_folders(root = :searchfolders, traversal = 'Deep', shape = 'Default', folder_type = nil)
36
+ super(root, traversal, shape, folder_type)
37
+ end
38
+
39
+
26
40
  def initialize(folder)
27
41
  super(folder)
28
42
  define_int_var :unread_count
@@ -22,13 +22,43 @@ module Viewpoint
22
22
  module EWS
23
23
  class Task < Item
24
24
 
25
+
26
+ # Create a Task in the Exchange Data Store from a hash
27
+ # @param [Hash] item A Hash of values based on values found here:
28
+ # http://msdn.microsoft.com/en-us/library/aa563930.aspx
29
+ # @param [String, Symbol] folder_id The folder to create this item in. Either a
30
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
31
+ # @param [String] disposition SaveOnly/SendOnly/SendAndSaveCopy
32
+ # See: http://msdn.microsoft.com/en-us/library/aa565209.aspx
33
+ # @example Typical Usage
34
+ # item = {
35
+ # :subject => {:text => 'Planning'},
36
+ # :body => {:body_type => 'Text', :text => 'This is a test'},
37
+ # :start_date => {:text => '2010-07-29T14:00:00'},
38
+ # :due_date => {:text => '2010-07-29T15:00:00'},
39
+ # }
40
+ # @example Minimal Usage
41
+ # item = {:subject => {:text => 'This is a test'}}
42
+ def self.create_item_from_hash(item, folder_id = :tasks, disposition = 'SaveOnly')
43
+ conn = Viewpoint::EWS::EWS.instance
44
+ resp = conn.ews.create_task_item(folder_id, item, disposition)
45
+ if(resp.status == 'Success')
46
+ resp = resp.items.shift
47
+ self.new(resp[resp.keys.first])
48
+ else
49
+ raise EwsError, "Could not create Task. #{resp.code}: #{resp.message}"
50
+ end
51
+ end
52
+
25
53
  # Create a Task in the Exchange Data Store
26
54
  #
55
+ # @param [nil, String] folder the folder to add the task to. If it is nil
56
+ # the Task will be placed in the default Task folder.
27
57
  # @param [String] subject The task subject
28
58
  # @param [String] body The task body
29
59
  # @param [DateTime] v_start The date/time when this task begins
30
60
  # @param [DateTime] v_end The date/time when this task is due
31
- def self.create_task(subject, body, v_start = nil, v_end = nil)
61
+ def self.create_task(folder, subject, body, v_start = nil, v_end = nil)
32
62
  item = {}
33
63
  item[:subject] = {:text => subject}
34
64
  item[:body] = {:text => body, :body_type => 'Text'} unless body.nil?
@@ -36,7 +66,7 @@ module Viewpoint
36
66
  item[:due_date] = {:text => v_end.to_s} unless v_end.nil?
37
67
 
38
68
  conn = Viewpoint::EWS::EWS.instance
39
- resp = conn.ews.create_task_item(nil, item, 'SaveOnly')
69
+ resp = conn.ews.create_task_item(folder, item, 'SaveOnly')
40
70
  if(resp.status == 'Success')
41
71
  resp = resp.items.shift
42
72
  self.new(resp[resp.keys.first])
@@ -23,31 +23,19 @@ module Viewpoint
23
23
  # This class represents a TaskFolderType object in the Exchange Data store.
24
24
  class TasksFolder < GenericFolder
25
25
 
26
- # Find Task subfolders of the passed root folder. If no parameters are passed
27
- # this method will search from the Root folder.
28
- # @param [Str] root An folder id, either a DistinguishedFolderId (must me a Symbol)
26
+ # Find folders of type Task
27
+ # @see GenericFolder.find_folders
28
+ # @param [String,Symbol] root An folder id, either a DistinguishedFolderId (must me a Symbol)
29
29
  # or a FolderId (String)
30
30
  # @param [String] traversal Shallow/Deep/SoftDeleted
31
+ # @param [String] shape the shape to return IdOnly/Default/AllProperties
32
+ # @param [optional, String] folder_type an optional folder type to limit the search to like 'IPF.Task'
31
33
  # @return [Array] Returns an Array of Folder or subclasses of Folder
32
- def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default')
33
- restr = {:restriction =>
34
- {:is_equal_to => {:field_uRI => {:field_uRI=>'folder:FolderClass'},:field_uRI_or_constant=>{:constant => {:value => 'IPF.Task'}}}}
35
- }
36
- resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal, {:base_shape => shape}, restr)
37
- if(resp.status == 'Success')
38
- folders = []
39
- resp.items.each do |f|
40
- f_type = f.keys.first.to_s.camel_case
41
- folders << (eval "#{f_type}.new(f[f.keys.first])")
42
- end
43
- return folders
44
- else
45
- raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
46
- end
34
+ def self.find_folders(root = :msgfolderroot, traversal = 'Deep', shape = 'Default', folder_type = 'IPF.Task')
35
+ super(root, traversal, shape, folder_type)
47
36
  end
48
37
 
49
38
 
50
-
51
39
  def initialize(folder)
52
40
  super(folder)
53
41
  define_int_var :unread_count