google_apps 0.4.9.9 → 0.5

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.
@@ -21,27 +21,6 @@ module GoogleApps
21
21
  openSearch: 'http://a9.com/-/spec/opensearchrss/1.0/'
22
22
  }
23
23
 
24
- MAPS = {
25
- user: {
26
- userName: :login,
27
- suspended: :suspended,
28
- familyName: :last_name,
29
- givenName: :first_name,
30
- limit: :quota,
31
- password: :password
32
- },
33
- nickname: {
34
- name: :nickname,
35
- userName: :user
36
- },
37
- group: {
38
- groupId: :id,
39
- groupName: :name,
40
- emailPermission: :permission,
41
- description: :description
42
- }
43
- }
44
-
45
24
  CATEGORY = {
46
25
  user: [['scheme', 'http://schemas.google.com/g/2005#kind'], ['term', 'http://schemas.google.com/apps/2006#user']],
47
26
  nickname: [['scheme', 'http://schemas.google.com/g/2005#kind'], ['term', 'http://schemas.google.com/apps/2006#nickname']]
@@ -50,13 +29,21 @@ module GoogleApps
50
29
 
51
30
  ENTRY_TAG = ["<atom:entry xmlns:atom=\"#{NAMESPACES[:atom]}\" xmlns:apps=\"#{NAMESPACES[:apps]}\" xmlns:gd=\"#{NAMESPACES[:gd]}\">", '</atom:entry>']
52
31
 
53
- DOCUMENTS = %w(user export group group_member message_attributes public_key feed nickname)
54
32
 
55
- # The idea is to make document distribution more dynamic.
56
- # Might be pointless but it's here for now.
57
- DOCUMENTS.each do |doc|
58
- eval "def #{doc}(*args)\n #{doc.camel_up}.new *args\nend" # Needs __file__ and __line__
59
- module_function doc.to_sym
33
+
34
+ #
35
+ # Adds a Module Function that creates a corresponding document.
36
+ # This allows for a centralized location for document creation.
37
+ #
38
+ # @param [String] type
39
+ #
40
+ # @visibility public
41
+ # @return
42
+ def add_doc_dispatcher(type)
43
+ eval "def #{type}(*args)\n #{type.camel_up}.new *args\nend" # Needs __file__ and __line__
44
+ module_function type.to_sym
60
45
  end
46
+
47
+ module_function :add_doc_dispatcher
61
48
  end
62
49
  end
@@ -1,6 +1,73 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- module Document
3
+ class Document
4
+ include Node
5
+
6
+ @types = []
7
+
8
+ #
9
+ # @param [String] doc
10
+ # @param [Hash] map
11
+ #
12
+ # @visibility public
13
+ # @return
14
+ def initialize(doc, map = {})
15
+ @doc = doc.nil? ? new_empty_doc : parse(doc)
16
+ @map = map
17
+ end
18
+
19
+
20
+ #
21
+ # Document keeps track of all it's subclasses. This makes
22
+ # it easy to look up the document types supported by the
23
+ # library.
24
+ #
25
+ # @param [Constant] subclass
26
+ #
27
+ # @visibility public
28
+ # @return
29
+ def self.inherited(subclass)
30
+ self.add_type subclass
31
+ Atom.add_doc_dispatcher self.sub_to_meth(subclass)
32
+ end
33
+
34
+
35
+ #
36
+ # Change subclass constant into a valid method name.
37
+ #
38
+ # @param [Constant] subclass should be a class name
39
+ #
40
+ # @visibility public
41
+ # @return
42
+ def self.sub_to_meth(subclass)
43
+ subclass.to_s.split('::').last.scan(/[A-Z][a-z0-9]+/).map(&:downcase).join('_')
44
+ end
45
+
46
+
47
+ #
48
+ # Accessor for the Document types array. This array is a
49
+ # list of all subclasses of GoogleApps::Atom::Document
50
+ #
51
+ # @visibility public
52
+ # @return
53
+ def self.types
54
+ @types
55
+ end
56
+
57
+
58
+ #
59
+ # Adds a subclass to the @types array.
60
+ #
61
+ # @param [Constant] type
62
+ #
63
+ # @visibility public
64
+ # @return
65
+ def self.add_type(type)
66
+ # TODO: Need to convert from const to symbol before adding
67
+ @types << type
68
+ end
69
+
70
+
4
71
  # parse takes xml, either a document or a string
5
72
  # and returns a parsed document. Since libxml-ruby
6
73
  # doesn't build a parse tree dynamically this
@@ -38,19 +105,37 @@ module GoogleApps
38
105
  end
39
106
 
40
107
 
41
- # find_values searches @document and assigns any values
108
+ # find_values searches @doc and assigns any values
42
109
  # to their corresponding instance variables. This is
43
110
  # useful when we've been given a string of XML and need
44
111
  # internal consistency in the object.
45
112
  #
46
113
  # find_values
47
114
  def find_values
48
- map_key = self.class.to_s.split(':').last.downcase.to_sym
49
- map = Atom::MAPS[map_key]
115
+ @doc.root.each do |entry|
116
+ intersect = @map.keys & entry.attributes.to_h.keys.map(&:to_sym)
117
+ set_instances(intersect, entry) unless intersect.empty?
118
+ end
119
+ end
120
+
50
121
 
51
- @document.root.each do |entry|
52
- intersect = map.keys & entry.attributes.to_h.keys.map(&:to_sym)
53
- set_instances(intersect, entry, map) unless intersect.empty?
122
+ # find_and_update updates the values for the specified
123
+ # attributes on the node specified by the given xpath
124
+ # value. It is ill behaved and will change any
125
+ # matching attributes in any node returned using the
126
+ # given xpath.
127
+ #
128
+ # find_and_update takes an xpath value and a hash of
129
+ # attribute names with current and new value pairs.
130
+ #
131
+ # find_and_update '/apps:nickname', name: ['Bob', 'Tom']
132
+ def find_and_update(xpath, attributes)
133
+ @doc.find(xpath).each do |node|
134
+ if node_match?(node, attributes)
135
+ attributes.each_key do |attrib|
136
+ node.attributes[attrib.to_s] = attributes[attrib][1]
137
+ end
138
+ end
54
139
  end
55
140
  end
56
141
 
@@ -66,27 +151,23 @@ module GoogleApps
66
151
  #
67
152
  # @visibility public
68
153
  # @return
69
- def set_instances(intersect, node, map)
154
+ def set_instances(intersect, node)
70
155
  intersect.each do |attribute|
71
- instance_variable_set "@#{map[attribute]}", check_value(node.attributes[attribute])
156
+ instance_variable_set "@#{@map[attribute]}", check_value(node.attributes[attribute])
72
157
  end
73
158
  end
74
159
 
75
160
 
76
161
  #
77
-
78
162
  # Sets instance variables for property list type documents.
79
163
  #
80
164
  # @visibility public
81
165
  # @return
82
166
  def attrs_from_props
83
- map_key = self.class.to_s.split(':').last.downcase.to_sym
84
- map = Atom::MAPS[map_key]
85
-
86
- @document.find('//apps:property').each do |entry|
167
+ @doc.find('//apps:property').each do |entry|
87
168
  prop_name = entry.attributes['name'].to_sym
88
- if map.keys.include?(prop_name)
89
- instance_variable_set "@#{map[prop_name]}", check_value(entry.attributes['value'])
169
+ if @map.keys.include?(prop_name)
170
+ instance_variable_set "@#{@map[prop_name]}", check_value(entry.attributes['value'])
90
171
  end
91
172
  end
92
173
  end
@@ -100,11 +181,11 @@ module GoogleApps
100
181
  # build_root returns an atom:entry node with an
101
182
  # apps:category element appropriate for the document
102
183
  # type.
103
- def build_root
184
+ def build_root(type)
104
185
  root = create_node(type: 'atom:entry')
105
186
 
106
- add_namespaces root, determine_namespaces
107
- root << create_node(type: 'apps:category', attrs: Atom::CATEGORY[type_to_sym]) if Atom::CATEGORY[type_to_sym]
187
+ add_namespaces root, determine_namespaces(type)
188
+ root << create_node(type: 'apps:category', attrs: Atom::CATEGORY[type.to_sym]) if Atom::CATEGORY[type.to_sym]
108
189
 
109
190
  root
110
191
  end
@@ -138,10 +219,10 @@ module GoogleApps
138
219
  # determine_namespaces
139
220
  #
140
221
  # determine_namespaces returns a hash
141
- def determine_namespaces
222
+ def determine_namespaces(type)
142
223
  ns = { atom: Atom::NAMESPACES[:atom], apps: Atom::NAMESPACES[:apps] }
143
224
 
144
- case type_to_s
225
+ case type.to_s
145
226
  when 'group', 'groupmember'
146
227
  ns[:gd] = Atom::NAMESPACES[:gd]
147
228
  end
@@ -159,10 +240,19 @@ module GoogleApps
159
240
  # @visibility public
160
241
  # @return
161
242
  def delete_node(xpath, attrs)
162
- @document.find(xpath).each do |node|
243
+ @doc.find(xpath).each do |node|
163
244
  node.remove! if node_match?(node, attrs)
164
245
  end
165
246
  end
247
+
248
+
249
+ # Prints the contents of @doc
250
+ #
251
+ # @visibility public
252
+ # @return
253
+ def to_s
254
+ @doc.to_s
255
+ end
166
256
  end
167
257
  end
168
258
  end
@@ -1,20 +1,17 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Export
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class Export < Document
7
4
  HEADER = 'HEADER_ONLY'
8
5
  FULL = 'FULL_MESSAGE'
9
6
 
10
7
  def initialize(xml = nil)
11
- @document = Atom::XML::Document.new
12
- @document.root = build_root
8
+ super(xml)
9
+ @doc.root = build_root(:export) unless xml
13
10
  end
14
11
 
15
- # to_s returns @document as a string.
12
+ # to_s returns @doc as a string.
16
13
  def to_s
17
- @document.to_s
14
+ @doc.to_s
18
15
  end
19
16
 
20
17
  # start_date specifies a start date for the extract.
@@ -29,7 +26,7 @@ module GoogleApps
29
26
  #
30
27
  # start_date '2012-01-01 00:00'
31
28
  #
32
- # start_date returns @document.root
29
+ # start_date returns @doc.root
33
30
  def start_date(date)
34
31
  add_prop('beginDate', date)
35
32
  end
@@ -46,7 +43,7 @@ module GoogleApps
46
43
  #
47
44
  # end_date '2012-01-01 08:30'
48
45
  #
49
- # end_date returns @document.root
46
+ # end_date returns @doc.root
50
47
  def end_date(date)
51
48
  add_prop('endDate', date)
52
49
  end
@@ -57,7 +54,7 @@ module GoogleApps
57
54
  #
58
55
  # include_deleted
59
56
  #
60
- # include_deleted returns @document.root
57
+ # include_deleted returns @doc.root
61
58
  def include_deleted
62
59
  add_prop('includeDeleted', 'true')
63
60
  end
@@ -69,7 +66,7 @@ module GoogleApps
69
66
  #
70
67
  # query 'from: Bob'
71
68
  #
72
- # query returns @document.root
69
+ # query returns @doc.root
73
70
  def query(query_string)
74
71
  add_prop('searchQuery', query_string)
75
72
  end
@@ -80,7 +77,7 @@ module GoogleApps
80
77
  #
81
78
  # content 'HEADER_ONLY'
82
79
  #
83
- # content returns @document.root
80
+ # content returns @doc.root
84
81
  def content(type)
85
82
  add_prop('packageContent', type)
86
83
  end
@@ -92,10 +89,10 @@ module GoogleApps
92
89
  # a mailbox extract as specified by the GoogleApps
93
90
  # Email Audit API.
94
91
  def set_header
95
- @document.root = Atom::XML::Node.new 'atom:entry'
92
+ @doc.root = Atom::XML::Node.new 'atom:entry'
96
93
 
97
- Atom::XML::Namespace.new(@document.root, 'atom', 'http://www.w3.org/2005/Atom')
98
- Atom::XML::Namespace.new(@document.root, 'apps', 'http://schemas.google.com/apps/2006')
94
+ Atom::XML::Namespace.new(@doc.root, 'atom', 'http://www.w3.org/2005/Atom')
95
+ Atom::XML::Namespace.new(@doc.root, 'apps', 'http://schemas.google.com/apps/2006')
99
96
  end
100
97
 
101
98
  # add_prop adds an element of the type: apps:property
@@ -105,7 +102,7 @@ module GoogleApps
105
102
  prop['name'] = name
106
103
  prop['value'] = value
107
104
 
108
- @document.root << prop
105
+ @doc.root << prop
109
106
  end
110
107
  end
111
108
  end
@@ -1,28 +1,27 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Feed
3
+ class Feed < Document
4
4
  # TODO: Google's feed responses are inconsistent. Will need special fun time, assholes.
5
-
6
- include Atom::Node
7
- include Atom::Document
8
-
9
- attr_reader :xml, :items, :next_page
5
+ attr_reader :doc, :items, :next_page
10
6
 
11
7
  # TODO: Figure out how to handle Group Members. The regex below
12
8
  # doesn't work in that case as group members also have group in
13
9
  # the id url.
14
- TYPE_MATCH = /<id.*(user|group.*member|nickname|group).*?<\/id/
10
+ TYPE_MATCH = /\/(user|nickname|group|member)/
15
11
 
16
12
 
17
13
  def initialize(xml)
18
- type = xml.match(TYPE_MATCH).captures[0]
19
- type.sub!(/\//, '_')
14
+ id_element = xml.scan(/<id.*?\/id/).first
15
+ matches = id_element.scan(TYPE_MATCH).flatten
16
+ type = matches.join '_'
20
17
 
21
- @xml = parse(xml)
22
- @items = entries_from document: @xml, type: type, entry_tag: 'entry'
18
+ super(xml)
19
+
20
+ @items = entries_from document: @doc, type: type, entry_tag: 'entry'
23
21
  end
24
22
 
25
- # TODO: Need to make sure this works for feeds other than user.
23
+
24
+ # TODO: There is no reason not to document. Especially with complicated methods.
26
25
  def entries_from(properties)
27
26
  type = properties[:type].to_sym
28
27
 
@@ -36,6 +35,7 @@ module GoogleApps
36
35
  end
37
36
 
38
37
 
38
+ # TODO: Obvious but still needs documentation.
39
39
  def set_next_page(node)
40
40
  @next_page = node.attributes[:href]
41
41
  end
@@ -1,21 +1,18 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Group
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class Group < Document
7
4
  attr_accessor :id, :name, :description, :permissions
8
5
 
9
- #ATTRIBUTES = %w(id name description perms).map(&:to_sym)
6
+ MAP = {
7
+ groupId: :id,
8
+ groupName: :name,
9
+ emailPermission: :permission,
10
+ description: :description
11
+ }
10
12
 
11
13
  def initialize(xml = nil)
12
- if xml
13
- @document = parse(xml)
14
- attrs_from_props
15
- else
16
- @document = Atom::XML::Document.new
17
- @document.root = build_root
18
- end
14
+ super(xml, MAP)
15
+ xml ? attrs_from_props : @doc.root = build_root(:group)
19
16
  end
20
17
 
21
18
  # new_group populates the Group XML document with
@@ -27,7 +24,7 @@ module GoogleApps
27
24
  # new_group id: 'ID', name: 'Name', description: 'Group Description',
28
25
  # perms: 'emailPermissions'
29
26
  #
30
- # new_group returns @document.root
27
+ # new_group returns @doc.root
31
28
  def new_group(group_data)
32
29
  [:id, :name].each { |attr| raise(ArgumentError, "Missing or Invalid Parameter(s)") unless group_data.key?(attr) }
33
30
  set_values group_data
@@ -35,26 +32,26 @@ module GoogleApps
35
32
 
36
33
 
37
34
  # set_values will add the specified group attributes
38
- # to @document. set_values accepts a hash with any of
35
+ # to @doc. set_values accepts a hash with any of
39
36
  # the following keys: id:, name:, description:, perms:
40
37
  #
41
38
  # set_values id: 'blah', description: 'Unexciting and uninspired'
42
39
  #
43
- # set_values returns @document.root
40
+ # set_values returns @doc.root
44
41
  def set_values(group_values)
45
42
  group_values.keys.each do |key|
46
43
  prop = Atom::XML::Node.new('apps:property')
47
44
  prop_name(prop, key)
48
45
  prop.attributes['value'] = group_values[key]
49
- @document.root << prop
46
+ @doc.root << prop
50
47
  end
51
48
 
52
- @document.root
49
+ @doc.root
53
50
  end
54
51
 
55
52
 
56
53
  def change_value(name, old_value, new_value)
57
- find_and_update @document, '//apps:property', { name => [old_value, new_value] }
54
+ find_and_update '//apps:property', { name => [old_value, new_value] }
58
55
  end
59
56
 
60
57
  # TODO: This needs to check all attributes of the element
@@ -62,7 +59,7 @@ module GoogleApps
62
59
  @id ? change_value(:value, @id, value) : set_values(id: value)
63
60
 
64
61
  @id = value
65
- @document = parse(@document)
62
+ @doc = parse(@doc)
66
63
  end
67
64
 
68
65
 
@@ -70,7 +67,7 @@ module GoogleApps
70
67
  @name ? change_value(:value, @name, value) : set_values(name: value)
71
68
 
72
69
  @name = value
73
- @document = parse(@document)
70
+ @doc = parse(@doc)
74
71
  end
75
72
 
76
73
 
@@ -78,7 +75,7 @@ module GoogleApps
78
75
  @permissions ? change_value(:value, @permissions, value) : set_values(perms: value)
79
76
 
80
77
  @permissions = value
81
- @document = parse(@document)
78
+ @doc = parse(@doc)
82
79
  end
83
80
 
84
81
 
@@ -86,13 +83,13 @@ module GoogleApps
86
83
  @description ? change_value(:value, @description, value) : set_values(description: value)
87
84
 
88
85
  @description = value
89
- @document = parse(@document)
86
+ @doc = parse(@doc)
90
87
  end
91
88
 
92
89
 
93
- # to_s returns @document as a String.
90
+ # to_s returns @doc as a String.
94
91
  def to_s
95
- @document.to_s
92
+ @doc.to_s
96
93
  end
97
94
 
98
95
  private
@@ -1,19 +1,11 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class GroupMember
4
- include Atom::Node
5
- include Atom::Document
6
-
3
+ class GroupMember < Document
7
4
  attr_accessor :member, :type
8
5
 
9
6
  def initialize(xml = nil)
10
- if xml
11
- @document = parse(xml)
12
- populate_self
13
- else
14
- @document = Atom::XML::Document.new
15
- @document.root = build_root
16
- end
7
+ super(xml)
8
+ xml ? populate_self : @doc.root = build_root(:groupmember)
17
9
  end
18
10
 
19
11
 
@@ -27,7 +19,7 @@ module GoogleApps
27
19
  def member=(member)
28
20
  @member.nil? ? add_node('memberId', member) : change_node('memberId', member)
29
21
 
30
- @document = parse(@document)
22
+ @doc = parse(@doc)
31
23
  @member = member
32
24
  end
33
25
 
@@ -35,38 +27,38 @@ module GoogleApps
35
27
  def type=(type)
36
28
  @type.nil? ? add_node('memberType', type) : change_node('memberType', type)
37
29
 
38
- @document = parse(@document)
30
+ @doc = parse(@doc)
39
31
  @type = type
40
32
  end
41
33
 
42
34
 
43
- # to_s returns @document as a string.
35
+ # to_s returns @doc as a string.
44
36
  def to_s
45
- @document.to_s
37
+ @doc.to_s
46
38
  end
47
39
 
48
40
 
49
41
  private
50
42
 
51
- #
52
- # @param [] type
53
- # @param [] value
54
- #
55
- # @visibility private
43
+ #
44
+ # @param [] type
45
+ # @param [] value
46
+ #
47
+ # @visibility private
56
48
  # @return
57
49
  def add_node(type, value)
58
- @document.root << create_node(type: 'apps:property', attrs: [['name', type], ['value', value]])
50
+ @doc.root << create_node(type: 'apps:property', attrs: [['name', type], ['value', value]])
59
51
  end
60
52
 
61
53
 
62
54
  def change_node(type, value)
63
- @document.find('//apps:property').each do |node|
55
+ @doc.find('//apps:property').each do |node|
64
56
  node.attributes['value'] = value if node.attributes['name'] == type
65
57
  end
66
58
  end
67
59
 
68
60
  # change_member changes the value attribute of the
69
- # apps:property element in @document to the value
61
+ # apps:property element in @doc to the value
70
62
  # of the provided argument. It also sets @member
71
63
  # to the provided argument.
72
64
  #
@@ -76,7 +68,7 @@ module GoogleApps
76
68
  def change_member(member)
77
69
  # This really should use find but I can't figure out how to
78
70
  # get the XPath to work with this document.
79
- @document.root.each do |node|
71
+ @doc.root.each do |node|
80
72
  node.attributes['value'] = member if node.attributes['value'] == @member
81
73
  end
82
74
 
@@ -84,12 +76,12 @@ module GoogleApps
84
76
  end
85
77
 
86
78
 
87
- #
88
- #
89
- # @visibility private
79
+ #
80
+ #
81
+ # @visibility private
90
82
  # @return
91
83
  def populate_self
92
- @document.find('//apps:property').each do |node|
84
+ @doc.find('//apps:property').each do |node|
93
85
  @member = node.attributes['value'] if node.attributes['name'] == 'memberId'
94
86
  @type = node.attributes['value'] if node.attributes['name'] == 'memberType'
95
87
  end
@@ -0,0 +1,41 @@
1
+ module GoogleApps
2
+ module Atom
3
+ class GroupOwner < Document
4
+ attr_reader :address
5
+
6
+ def initialize(xml = nil)
7
+ super(xml)
8
+ xml ? attrs_from_props : @doc.root = build_root(:group)
9
+ end
10
+
11
+
12
+ #
13
+ # @param [String] address email address of the owner object.
14
+ #
15
+ # @visibility public
16
+ # @return
17
+ def add_address(address)
18
+ add_prop_node('email', address)
19
+ @doc = parse @doc
20
+ end
21
+
22
+
23
+ def update_address(address)
24
+ find_and_update '//apps:property', { name: ['email', 'email'], value: [@address, address] }
25
+ @doc = parse @doc
26
+ end
27
+
28
+
29
+ #
30
+ # @param [String] value Email address for the owner object
31
+ #
32
+ # @visibility public
33
+ # @return
34
+ def address=(value)
35
+ @address ? update_address(value) : add_address(value)
36
+
37
+ @address = value
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,20 +1,24 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class MessageAttributes
4
- include Document
5
- include Node
6
-
3
+ class MessageAttributes < Document
7
4
  attr_reader :labels
8
5
  attr_accessor :property
9
6
 
7
+ DRAFT = 'IS_DRAFT'
8
+ INBOX = 'IS_INBOX'
9
+ SENT = 'IS_SENT'
10
+ TRASH = 'IS_TRASH'
11
+ STARRED = 'IS_STARRED'
12
+ UNREAD = 'IS_UNREAD'
13
+
10
14
  def initialize(xml = nil)
15
+ super(xml)
16
+
11
17
  if xml
12
- @document = parse(xml)
13
18
  find_labels
14
19
  get_item_property
15
20
  else
16
21
  @labels = []
17
- @document = Atom::XML::Document.new
18
22
  set_header
19
23
  end
20
24
  end
@@ -23,8 +27,8 @@ module GoogleApps
23
27
  property = Atom::XML::Node.new 'apps:mailItemProperty'
24
28
  property['value'] = prop
25
29
 
26
- @document.root << property
27
- @document = parse(@document)
30
+ @doc.root << property
31
+ @doc = parse(@doc)
28
32
  end
29
33
 
30
34
  def property=(value)
@@ -35,9 +39,9 @@ module GoogleApps
35
39
  label = Atom::XML::Node.new 'apps:label'
36
40
  label['labelName'] = name
37
41
 
38
- @document.root << label
42
+ @doc.root << label
39
43
  @labels << name
40
- @document = parse(@document)
44
+ @doc = parse(@doc)
41
45
  end
42
46
 
43
47
  def <<(value)
@@ -50,19 +54,19 @@ module GoogleApps
50
54
  end
51
55
 
52
56
  def to_s
53
- @document.to_s
57
+ @doc.to_s
54
58
  end
55
59
 
56
60
  private
57
61
 
58
62
  def set_header
59
- @document.root = Atom::XML::Node.new 'atom:entry' # API Docs show just entry here
63
+ @doc.root = Atom::XML::Node.new 'atom:entry' # API Docs show just entry here
60
64
 
61
- Atom::XML::Namespace.new(@document.root, 'atom', 'http://www.w3.org/2005/Atom') # API Docs show this as just xmlns
62
- Atom::XML::Namespace.new(@document.root, 'apps', 'http://schemas.google.com/apps/2006')
65
+ Atom::XML::Namespace.new(@doc.root, 'atom', 'http://www.w3.org/2005/Atom') # API Docs show this as just xmlns
66
+ Atom::XML::Namespace.new(@doc.root, 'apps', 'http://schemas.google.com/apps/2006')
63
67
 
64
- @document.root << category
65
- @document.root << content
68
+ @doc.root << category
69
+ @doc.root << content
66
70
  end
67
71
 
68
72
  def category
@@ -82,11 +86,11 @@ module GoogleApps
82
86
  end
83
87
 
84
88
  def find_labels
85
- @labels = @document.find('//apps:label').inject([]) { |labels, entry| labels << entry.attributes['labelName']; labels }
89
+ @labels = @doc.find('//apps:label').inject([]) { |labels, entry| labels << entry.attributes['labelName']; labels }
86
90
  end
87
91
 
88
92
  def get_item_property
89
- @property = @document.find('//apps:mailItemProperty').first.attributes['value']
93
+ @property = @doc.find('//apps:mailItemProperty').first.attributes['value']
90
94
  end
91
95
  end
92
96
  end
@@ -1,16 +1,16 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class Nickname
4
- include Atom::Node
5
- include Atom::Document
3
+ class Nickname < Document
4
+ attr_reader :nickname, :user, :doc
6
5
 
7
- attr_reader :nickname, :user, :document
8
-
9
- ELEMENTS = { nick: ['apps:nickname', 'name'], user: ['apps:login', 'userName'] }
6
+ MAP = {
7
+ name: :nickname,
8
+ userName: :user
9
+ }
10
10
 
11
11
  def initialize(xml = nil)
12
- @document = Atom::XML::Document.new
13
- @document.root = build_root
12
+ super(xml, MAP)
13
+ @doc.root = build_root(:nickname) unless xml
14
14
  end
15
15
 
16
16
  # nickname= sets the nickname value on the object and in the
@@ -20,7 +20,7 @@ module GoogleApps
20
20
  #
21
21
  # nickname= returns the new nickname value
22
22
  def nickname=(nick)
23
- @nickname ? find_and_update(@document, '//apps:nickname', name: [@nickname, nick]) : create('nickname', nick)
23
+ @nickname ? find_and_update('//apps:nickname', name: [@nickname, nick]) : create('nickname', nick)
24
24
 
25
25
  @nickname = nick
26
26
  end
@@ -34,7 +34,7 @@ module GoogleApps
34
34
  #
35
35
  # user= returns the new username value
36
36
  def user=(username)
37
- @user ? find_and_update(@document, '//apps:login', userName: [@user, username]) : create('login', username)
37
+ @user ? find_and_update('//apps:login', userName: [@user, username]) : create('login', username)
38
38
 
39
39
  @user = username
40
40
  end
@@ -42,7 +42,7 @@ module GoogleApps
42
42
 
43
43
  # to_s returns the underlying XML document as a string.
44
44
  def to_s
45
- @document.to_s
45
+ @doc.to_s
46
46
  end
47
47
 
48
48
 
@@ -50,7 +50,7 @@ module GoogleApps
50
50
  private
51
51
 
52
52
 
53
- # create adds the specified node to @document. It takes
53
+ # create adds the specified node to @doc. It takes
54
54
  # a type and a value as arguments.
55
55
  #
56
56
  # create 'nickname', 'Bob'
@@ -59,12 +59,12 @@ module GoogleApps
59
59
  def create(type, value)
60
60
  case type
61
61
  when 'nickname'
62
- @document.root << create_node(type: 'apps:nickname', attrs: [['name', value]])
62
+ @doc.root << create_node(type: 'apps:nickname', attrs: [['name', value]])
63
63
  when 'login'
64
- @document.root << create_node(type: 'apps:login', attrs: [['userName', value]])
64
+ @doc.root << create_node(type: 'apps:login', attrs: [['userName', value]])
65
65
  end
66
66
 
67
- @document = parse @document
67
+ @doc = parse @doc
68
68
  end
69
69
  end
70
70
  end
@@ -20,6 +20,19 @@ module GoogleApps
20
20
  end
21
21
 
22
22
 
23
+ #
24
+ # @param [String] name the value for the name attribute
25
+ # @param [String] value the value for the value attribute
26
+ #
27
+ # @visibility public
28
+ # @return
29
+ def add_prop_node(name, value, node = nil)
30
+ node ||= @doc.root
31
+
32
+ node << create_node({type: 'apps:property', attrs: [['name', name], ['value', value]]})
33
+ end
34
+
35
+
23
36
  # add_namespaces adds the specified namespaces to the
24
37
  # specified node. namespaces should be a hash of name,
25
38
  # value pairs.
@@ -52,33 +65,11 @@ module GoogleApps
52
65
  end
53
66
 
54
67
 
55
- # update_node updates the values for the specified
56
- # attributes on the node specified by the given xpath
57
- # value. It is ill behaved and will change any
58
- # matching attributes in any node returned using the
59
- # given xpath.
60
- #
61
- # update_node takes a document (must be parsed), an
62
- # xpath value and a hash of attribute names with
63
- # current and new value pairs.
64
- #
65
- # update_node document, '/apps:nickname', name: ['Bob', 'Tom']
66
- def find_and_update(document, xpath, attributes)
67
- document.find(xpath).each do |node|
68
- if node_match?(node, attributes)
69
- attributes.each_key do |attrib|
70
- node.attributes[attrib.to_s] = attributes[attrib][1]
71
- end
72
- end
73
- end
74
- end
75
-
76
-
77
68
  # node_match? checks that each value for each specified
78
69
  # attribute matches the specified value.
79
70
  def node_match?(node, attributes)
80
71
  attributes.keys.inject(true) do |result, key|
81
- result and node.attributes[key.to_s] == attributes[key][0]
72
+ result and node.attributes[key].to_s == attributes[key][0]
82
73
  end
83
74
  end
84
75
 
@@ -1,14 +1,11 @@
1
1
  module GoogleApps
2
2
  module Atom
3
- class PublicKey
4
- include Atom::Node
5
- include Atom::Document
6
-
7
- attr_reader :document
3
+ class PublicKey < Document
4
+ attr_reader :doc
8
5
 
9
6
  def initialize
10
- @document = Atom::XML::Document.new
11
- @document.root = build_root
7
+ super(nil)
8
+ @doc.root = build_root :publickey
12
9
  end
13
10
 
14
11
  # new_key adds the actual key to the PublicKey
@@ -16,18 +13,18 @@ module GoogleApps
16
13
  #
17
14
  # new_key 'key'
18
15
  #
19
- # new_key returns @document.root
16
+ # new_key returns @doc.root
20
17
  def new_key(key)
21
18
  property = Atom::XML::Node.new('apps:property')
22
19
  property['name'] = 'publicKey'
23
20
  property['value'] = Base64.encode64 key
24
21
 
25
- @document.root << property
22
+ @doc.root << property
26
23
  end
27
24
 
28
- # to_s returns @document as a String
25
+ # to_s returns @doc as a String
29
26
  def to_s
30
- @document.to_s
27
+ @doc.to_s
31
28
  end
32
29
  end
33
30
  end
@@ -2,19 +2,25 @@ module GoogleApps
2
2
  module Atom
3
3
  # TODO: Move User attribute map to user class
4
4
  # TODO: Update attribute map to include @ for instance variables
5
- class User
6
- include Atom::Node
7
- include Atom::Document
8
-
9
- attr_reader :document, :login, :suspended, :first_name, :last_name, :quota, :password
5
+ class User < Document
6
+ attr_reader :doc, :login, :suspended, :first_name, :last_name, :quota, :password
7
+
8
+ MAP = {
9
+ userName: :login,
10
+ suspended: :suspended,
11
+ familyName: :last_name,
12
+ givenName: :first_name,
13
+ limit: :quota,
14
+ password: :password
15
+ }
10
16
 
11
17
  def initialize(xml = nil)
12
18
  if xml
13
- @document = parse(xml)
19
+ super(xml, MAP)
14
20
  find_values
15
21
  else
16
- @document = new_empty_doc
17
- @document.root = build_root
22
+ super(nil, MAP)
23
+ @doc.root = build_root :user
18
24
  end
19
25
  end
20
26
 
@@ -34,15 +40,15 @@ module GoogleApps
34
40
  # add_node creates the specified node in the user document. It
35
41
  # takes a type/name and an array of attribute, value pairs as
36
42
  # arguments. It also parses the new document and saves the
37
- # copy in @document
43
+ # copy in @doc
38
44
  #
39
45
  # add_node 'apps:login', [['userName', 'Zanzabar']]
40
46
  #
41
47
  # add_node returns a parsed copy of the new document.
42
- def add_node(type, attrs) # TODO: Should take a target argument rather than only appending to @document.root
43
- @document.root << create_node(type: type, attrs: attrs)
48
+ def add_node(type, attrs) # TODO: Should take a target argument rather than only appending to @doc.root
49
+ @doc.root << create_node(type: type, attrs: attrs)
44
50
 
45
- @document = parse @document
51
+ @doc = parse @doc
46
52
  end
47
53
 
48
54
 
@@ -51,13 +57,13 @@ module GoogleApps
51
57
  #
52
58
  # update_node 'apps:login', :userName, true
53
59
  def update_node(type, attribute, value)
54
- find_and_update @document, "//#{type}", { attribute => [instance_variable_get("@#{Atom::MAPS[:user][attribute]}").to_s, value.to_s]}
60
+ find_and_update "//#{type}", { attribute => [instance_variable_get("@#{MAP[attribute]}").to_s, value.to_s]}
55
61
  end
56
62
 
57
63
 
58
64
  # TODO: Move this method.
59
65
  def node(name)
60
- @document.find_first("//#{name}")
66
+ @doc.find_first("//#{name}")
61
67
  end
62
68
 
63
69
 
@@ -152,9 +158,9 @@ module GoogleApps
152
158
  end
153
159
 
154
160
 
155
- # to_s returns @document as a string
161
+ # to_s returns @doc as a string
156
162
  def to_s
157
- @document.to_s
163
+ @doc.to_s
158
164
  end
159
165
 
160
166
 
@@ -162,7 +168,7 @@ module GoogleApps
162
168
 
163
169
  # new_doc re-initializes the XML document.
164
170
  def new_doc
165
- @document = Atom::XML::Document.new
171
+ @doc = Atom::XML::Document.new
166
172
  end
167
173
  end
168
174
  end
@@ -1,11 +1,12 @@
1
1
  module GoogleApps
2
2
  class DocumentHandler
3
+ # TODO: Should get type list from Document Parent class, not format namespace.
3
4
  attr_accessor :format
4
5
 
5
6
  def initialize(args)
6
7
  set_format args[:format]
7
8
  end
8
-
9
+
9
10
 
10
11
  # create_doc creates a document of the specified format
11
12
  # from the given string.
@@ -51,11 +52,16 @@ module GoogleApps
51
52
  def look_up_doc_types
52
53
  case @format
53
54
  when :atom, :xml
54
- Atom::DOCUMENTS
55
+ Atom::Document.types.inject([]) { |types, subclass| types | [sub_to_meth(subclass)] }
55
56
  end
56
57
  end
57
58
 
58
59
 
60
+ def sub_to_meth(subclass) # TODO: This shouldn't be both here and in GoogleApps::Atom::Document
61
+ subclass.to_s.split('::').last.scan(/[A-Z][a-z0-9]+/).map(&:downcase).join('_')
62
+ end
63
+
64
+
59
65
  # set_format Sets @format and @documents
60
66
  def set_format(format)
61
67
  @format = format
@@ -63,8 +63,8 @@ module GoogleApps
63
63
  # the HTTP response object on failure.
64
64
  def request_export(username, document)
65
65
  result = add(@export + "/#{username}", :export_response, document)
66
-
67
- result.find('//apps:property').inject(nil) do |request_id, node|
66
+
67
+ result.find('//apps:property').inject(nil) do |request_id, node|
68
68
  node.attributes['name'] == 'requestId' ? node.attributes['value'].to_i : request_id
69
69
  end
70
70
  end
@@ -188,23 +188,26 @@ module GoogleApps
188
188
 
189
189
  fetch_feed(page, limit, :feed)
190
190
 
191
- #@response
191
+ #@response
192
192
  return_all
193
193
  end
194
194
 
195
195
 
196
196
  # Retrieves the members of the requested group.
197
- #
197
+ #
198
198
  # @param [String] group_id the Group ID in the Google Apps Environment
199
- #
199
+ #
200
200
  # @visibility public
201
- # @return
201
+ # @return
202
202
  def get_members_of(group_id, options = {})
203
203
  options[:extra] = "/#{group_id}/member"
204
204
  get_all :groups, options
205
205
  end
206
206
 
207
207
 
208
+ # TODO: Refactor add tos.
209
+
210
+
208
211
  # add_member_to adds a member to a group in the domain.
209
212
  # It takes a group_id and a GoogleApps::Atom::GroupMember
210
213
  # document as arguments.
@@ -217,6 +220,18 @@ module GoogleApps
217
220
  end
218
221
 
219
222
 
223
+ #
224
+ # @param [String] group_id The ID for the group being modified
225
+ # @param [GoogleApps::Atom::GroupOwner] document The XML document with the owner address
226
+ #
227
+ # @visibility public
228
+ # @return
229
+ def add_owner_to(group_id, document)
230
+ add(@group + "/#{group_id}/owner", nil, document)
231
+ end
232
+
233
+ # TODO: Refactor delete froms.
234
+
220
235
  # delete_member_from removes a member from a group in the
221
236
  # domain. It takes a group_id and member_id as arguments.
222
237
  #
@@ -228,6 +243,17 @@ module GoogleApps
228
243
  end
229
244
 
230
245
 
246
+ #
247
+ # @param [String] group_id Email address of group
248
+ # @param [String] owner_id Email address of owner to remove
249
+ #
250
+ # @visibility public
251
+ # @return
252
+ def delete_owner_from(group_id, owner_id)
253
+ delete(@group + "/#{group_id}/owner", owner_id)
254
+ end
255
+
256
+
231
257
  # get_nicknames_for retrieves all the nicknames associated
232
258
  # with the requested user. It takes the username as a string.
233
259
  #
@@ -386,11 +412,12 @@ module GoogleApps
386
412
  SUCCESS_CODES.include?(@response.code.to_i)
387
413
  end
388
414
 
389
-
390
- #
415
+
416
+ #
417
+
391
418
  # Takes all the items in each feed and puts them into one array.
392
- #
393
- # @visibility private
419
+ #
420
+ # @visibility private
394
421
  # @return Array of Documents
395
422
  def return_all
396
423
  @feeds.inject([]) do |results, feed|
data/lib/google_apps.rb CHANGED
@@ -11,4 +11,5 @@ require 'google_apps/atom/public_key'
11
11
  require 'google_apps/atom/export'
12
12
  require 'google_apps/atom/message_attributes'
13
13
  require 'google_apps/atom/group_member'
14
- require 'google_apps/atom/nickname'
14
+ require 'google_apps/atom/nickname'
15
+ require 'google_apps/atom/group_owner'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_apps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9.9
4
+ version: '0.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-15 00:00:00.000000000 Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libxml-ruby
@@ -40,6 +40,7 @@ files:
40
40
  - lib/google_apps/atom/feed.rb
41
41
  - lib/google_apps/atom/group.rb
42
42
  - lib/google_apps/atom/group_member.rb
43
+ - lib/google_apps/atom/group_owner.rb
43
44
  - lib/google_apps/atom/message_attributes.rb
44
45
  - lib/google_apps/atom/nickname.rb
45
46
  - lib/google_apps/atom/node.rb