puree 0.14.0 → 0.15.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.
@@ -1,25 +1,31 @@
1
1
  module Puree
2
2
 
3
- # Collection resource
3
+ # Collection of resources
4
4
  #
5
- class Collection < Resource
5
+ class Collection
6
6
 
7
- # @param api [Symbol]
7
+ # @param resource [Symbol]
8
8
  # @param endpoint [String]
9
9
  # @param optional username [String]
10
10
  # @param optional password [String]
11
- def initialize(api: nil,
11
+ # @param optional basic_auth [Boolean]
12
+ def initialize(resource: nil,
12
13
  endpoint: nil,
13
14
  username: nil,
14
- password: nil)
15
- super(api: api,
16
- endpoint: endpoint,
17
- username: username,
18
- password: password)
15
+ password: nil,
16
+ basic_auth: nil)
17
+ @resource_type = resource
18
+ @api_map = Puree::Map.new.get
19
+ @endpoint = endpoint.nil? ? Puree.endpoint : endpoint
20
+ @basic_auth = basic_auth.nil? ? Puree.basic_auth : basic_auth
21
+ if @basic_auth === true
22
+ @username = username.nil? ? Puree.username : username
23
+ @password = password.nil? ? Puree.password : password
24
+ end
19
25
  @uuids = []
20
26
  end
21
27
 
22
- # Get
28
+ # Gets an array of objects of resource type specified in constructor
23
29
  #
24
30
  # @param optional limit [Integer]
25
31
  # @param optional offset [Integer]
@@ -27,27 +33,21 @@ module Puree
27
33
  # @param optional created_end [String]
28
34
  # @param optional modified_start [String]
29
35
  # @param optional modified_end [String]
30
- # @return [HTTParty::Response]
36
+ # @param optional full [Boolean]
37
+ # @return [Array<Object>]
31
38
  def get(
32
39
  limit: 20,
33
40
  offset: 0,
34
41
  created_start: nil,
35
42
  created_end: nil,
36
43
  modified_start: nil,
37
- modified_end: nil)
38
-
39
- missing = missing_credentials
40
- if !missing.empty?
41
- missing.each do |m|
42
- puts "#{self.class.name}" + '#' + "#{__method__} missing #{m}"
43
- end
44
- exit
45
- end
46
- # strip any trailing slash
47
- @endpoint = @endpoint.sub(/(\/)+$/, '')
48
- @auth = Base64::strict_encode64(@username + ':' + @password)
44
+ modified_end: nil,
45
+ full: true,
46
+ rendering: :xml_long
47
+ )
49
48
 
50
49
  @options = {
50
+ basic_auth: @basic_auth,
51
51
  latest_api: true,
52
52
  resource_type: @resource_type.to_sym,
53
53
  rendering: :system,
@@ -56,12 +56,30 @@ module Puree
56
56
  created_start: created_start,
57
57
  created_end: created_end,
58
58
  modified_start: modified_start,
59
- modified_end: modified_end
60
- }
61
- headers = {
62
- 'Accept' => 'application/xml',
63
- 'Authorization' => 'Basic ' + @auth
59
+ modified_end: modified_end,
60
+ full: full,
61
+ record_rendering: rendering
64
62
  }
63
+
64
+ missing = missing_credentials
65
+ if !missing.empty?
66
+ missing.each do |m|
67
+ puts "#{self.class.name}" + '#' + "#{__method__} missing #{m}"
68
+ end
69
+ exit
70
+ end
71
+
72
+ # strip any trailing slash
73
+ @endpoint = @endpoint.sub(/(\/)+$/, '')
74
+
75
+ headers = {}
76
+ headers['Accept'] = 'application/xml'
77
+
78
+ if @options[:basic_auth] === true
79
+ @auth = Base64::strict_encode64(@username + ':' + @password)
80
+ headers['Authorization'] = 'Basic ' + @auth
81
+ end
82
+
65
83
  query = {}
66
84
 
67
85
  query['rendering'] = @options[:rendering]
@@ -90,10 +108,54 @@ module Puree
90
108
  query['modifiedDate.toDate'] = @options[:modified_end]
91
109
  end
92
110
 
93
- @response = HTTParty.get(build_url, query: query, headers: headers)
111
+ if @options['rendering']
112
+ query['rendering'] = @options['rendering']
113
+ end
114
+
115
+ # @response = HTTParty.get(build_url, query: query, headers: headers)
116
+
117
+ begin
118
+ # p self.inspect
119
+ # p build_url
120
+ # p query
121
+ # p headers
122
+ # @response = HTTParty.get(build_url, query: query, headers: headers, timeout: 120)
123
+ url = build_url
124
+ req = HTTP.headers accept: 'application/xml'
125
+ if @options[:basic_auth]
126
+ req = req.auth headers['Authorization']
127
+ end
128
+ @response = req.get(url, params: query)
129
+ @doc = Nokogiri::XML @response.body
130
+ @doc.remove_namespaces!
131
+
132
+ code = @response.code
133
+ # body = @response.body
134
+ # puts "#{self.class.name} #{code}"
135
+ # puts "#{self.class.name} #{body}"
136
+
137
+ rescue HTTP::Error => e
138
+ puts 'HTTP::Error '+ e.message
139
+ end
140
+
141
+ if @options[:full]
142
+ collect_resource
143
+ else
144
+ data = []
145
+ uuid.each do |u|
146
+ o = {}
147
+ o['uuid'] = u
148
+ data << o
149
+ end
150
+ data
151
+ end
152
+
94
153
  end
95
154
 
96
155
 
156
+ private
157
+
158
+
97
159
  # Array of UUIDs
98
160
  #
99
161
  # @return [Array<String>]
@@ -103,18 +165,85 @@ module Puree
103
165
  end
104
166
 
105
167
 
168
+ def collect_resource
169
+ data = []
170
+ resource_class = 'Puree::' + @resource_type.to_s.capitalize
106
171
 
107
- private
108
-
172
+ if @options[:basic_auth] === true
173
+ r = Object.const_get(resource_class).new endpoint: @endpoint,
174
+ username: @username,
175
+ password: @password,
176
+ basic_auth: true
177
+ else
178
+ r = Object.const_get(resource_class).new endpoint: @endpoint
179
+ end
180
+ # whitelist symbol
181
+ if @api_map[:resource_type].has_key?(@resource_type)
182
+ uuid.each do |u|
183
+ record = r.find uuid: u,
184
+ rendering: @options[:record_rendering]
185
+ # puts JSON.pretty_generate( record, :indent => ' ')
186
+ # p u
187
+ data << record
188
+ end
189
+ data
190
+ else
191
+ puts 'Invalid resource class'
192
+ exit
193
+ end
194
+ end
109
195
 
110
196
  def collect_uuid
197
+ @uuids = []
111
198
  path = '//renderedItem/@renderedContentUUID'
112
199
  xpath_result = xpath_query path
113
200
  xpath_result.each { |i| @uuids << i.text.strip }
114
201
  end
115
202
 
203
+ def service_name
204
+ resource_type = @options[:resource_type]
205
+ @api_map[:resource_type][resource_type][:service]
206
+ end
207
+
208
+ def service_response_name
209
+ resource_type = @options[:resource_type]
210
+ @api_map[:resource_type][resource_type][:response]
211
+ end
212
+
213
+ def build_url
214
+ service = service_name
215
+ if @options[:latest_api] === false
216
+ service_api_mode = service
217
+ else
218
+ service_api_mode = service + '.current'
219
+ end
220
+ @endpoint + '/' + service_api_mode
221
+ end
222
+
223
+ def xpath_query(path)
224
+ @doc.xpath path
225
+ end
226
+
227
+
228
+ def missing_credentials
229
+ missing = []
230
+ if @endpoint.nil?
231
+ missing << 'endpoint'
232
+ end
233
+
234
+ if @options[:basic_auth] === true
235
+ if @username.nil?
236
+ missing << 'username'
237
+ end
238
+ if @password.nil?
239
+ missing << 'password'
240
+ end
241
+ end
242
+
243
+ missing
244
+ end
245
+
116
246
  alias :find :get
117
247
 
118
248
  end
119
-
120
249
  end
@@ -2,16 +2,12 @@ module Puree
2
2
 
3
3
  module Configuration
4
4
 
5
- class << self
6
-
7
- attr_accessor :endpoint, :username, :password
5
+ attr_accessor :endpoint, :username, :password, :basic_auth
8
6
 
9
7
  def configure
10
8
  yield self
11
9
  end
12
10
 
13
- end
14
-
15
11
  end
16
12
 
17
13
  end
@@ -7,18 +7,21 @@ module Puree
7
7
  # @param endpoint [String]
8
8
  # @param optional username [String]
9
9
  # @param optional password [String]
10
- def initialize(endpoint: nil, username: nil, password: nil)
10
+ # @param optional basic_auth [Boolean]
11
+ def initialize(endpoint: nil, username: nil, password: nil, basic_auth: nil)
11
12
  super(api: :dataset,
12
13
  endpoint: endpoint,
13
14
  username: username,
14
- password: password)
15
+ password: password,
16
+ basic_auth: basic_auth)
15
17
  end
16
18
 
19
+
17
20
  # Link
18
21
  #
19
22
  # @return [Array<Hash>]
20
23
  def link
21
- path = '//links/link'
24
+ path = '/links/link'
22
25
  xpath_result = xpath_query path
23
26
  data = []
24
27
  xpath_result.each { |i|
@@ -30,33 +33,32 @@ module Puree
30
33
  data.uniq
31
34
  end
32
35
 
33
- # Organisation
36
+ # Owner
34
37
  #
35
38
  # @return [Hash]
36
- def organisation
37
- path = '//content/managedBy'
39
+ def owner
40
+ path = '/managedBy'
38
41
  xpath_result = xpath_query path
39
42
  o = {}
40
43
  o['uuid'] = xpath_result.xpath('@uuid').text.strip
41
44
  o['name'] = xpath_result.xpath('name/localizedString').text.strip
42
45
  o['type'] = xpath_result.xpath('typeClassification/term/localizedString').text.strip
43
- o
46
+ o
44
47
  end
45
48
 
46
49
  # Publisher
47
50
  #
48
51
  # @return [String]
49
52
  def publisher
50
- path = '//publisher/name'
51
- xpath_result = xpath_query path
52
- xpath_result ? xpath_result.text.strip : ''
53
+ path = '/publisher/name'
54
+ xpath_query_for_single_value path
53
55
  end
54
56
 
55
57
  # Combines project and publication
56
58
  #
57
- # @return [Hash]
59
+ # @return [Array<Hash>]
58
60
  def associated
59
- path = '//associatedContent//relatedContent'
61
+ path = '/associatedContent//relatedContent'
60
62
  xpath_result = xpath_query path
61
63
  data_arr = []
62
64
  xpath_result.each { |i|
@@ -94,16 +96,15 @@ module Puree
94
96
  #
95
97
  # @return [String]
96
98
  def title
97
- path = '//title/localizedString'
98
- xpath_result = xpath_query path
99
- xpath_result ? xpath_result.text.strip : ''
99
+ path = '/title/localizedString'
100
+ xpath_query_for_single_value path
100
101
  end
101
102
 
102
103
  # Keyword
103
104
  #
104
105
  # @return [Array<String>]
105
106
  def keyword
106
- path = '//keywordGroups/keywordGroup/keyword/userDefinedKeyword/freeKeyword'
107
+ path = '/keywordGroups/keywordGroup/keyword/userDefinedKeyword/freeKeyword'
107
108
  xpath_result = xpath_query path
108
109
  data_arr = xpath_result.map { |i| i.text.strip }
109
110
  data_arr.uniq
@@ -113,84 +114,84 @@ module Puree
113
114
  #
114
115
  # @return [String]
115
116
  def description
116
- path = '//descriptions/classificationDefinedField/value/localizedString'
117
+ path = '/descriptions/classificationDefinedField/value/localizedString'
118
+ xpath_query_for_single_value path
119
+ end
120
+
121
+ # Organisation
122
+ #
123
+ # @return [Array<Hash>]
124
+ def organisation
125
+ path = '/organisations/organisation'
117
126
  xpath_result = xpath_query path
118
- xpath_result ? xpath_result.text.strip : ''
127
+ data = []
128
+ xpath_result.each do |i|
129
+ o = {}
130
+ o['uuid'] = i.xpath('@uuid').text.strip
131
+ o['name'] = i.xpath('name/localizedString').text.strip
132
+ o['type'] = i.xpath('typeClassification/term/localizedString').text.strip
133
+ data << o
134
+ end
135
+ data
119
136
  end
120
137
 
121
138
  # Person (internal, external, other)
122
139
  #
123
- # @return [Hash]
140
+ # @return [Array<Hash>]
124
141
  def person
125
- data = node('persons')
126
- persons = {}
127
- if !data.nil? && !data.empty?
128
- data = data['dataSetPersonAssociation']
129
- else
130
- return persons
131
- end
132
- internal_persons = []
133
- external_persons = []
134
- other_persons = []
135
- case data
136
- when Array
137
- data.each do |d|
138
- person = generic_person d
139
- if d.key? 'person'
140
- person['uuid'] = d['person']['uuid'].strip
141
- internal_persons << person
142
- end
143
- if d.key? 'externalPerson'
144
- person['uuid'] = d['externalPerson']['uuid'].strip
145
- external_persons << person
146
- end
147
- if !d.key?('person') && !d.key?('externalPerson')
148
- person['uuid'] = ''
149
- other_persons << person
150
- end
151
- end
152
- when Hash
153
- person = generic_person data
154
- if data.key? 'person'
155
- person['uuid'] = data['person']['uuid'].strip
156
- internal_persons << person
157
- end
158
- if data.key? 'externalPerson'
159
- person['uuid'] = data['externalPerson']['uuid'].strip
160
- external_persons << person
161
- end
162
- if !data.key?('person') && !data.key?('externalPerson')
163
- person['uuid'] = ''
164
- other_persons << person
165
- end
142
+ data = {}
143
+ # internal
144
+ path = '/persons/dataSetPersonAssociation'
145
+ xpath_result = xpath_query path
146
+ internal = []
147
+ external = []
148
+ other = []
149
+
150
+ xpath_result.each do |i|
151
+ o = {}
152
+ name = {}
153
+ name['first'] = i.xpath('name/firstName').text.strip
154
+ name['last'] = i.xpath('name/lastName').text.strip
155
+ o['name'] = name
156
+ o['role'] = i.xpath('personRole/term/localizedString').text.strip
157
+
158
+ uuid_internal = i.at_xpath('person/@uuid')
159
+ uuid_external = i.at_xpath('externalPerson/@uuid')
160
+ if uuid_internal
161
+ o['uuid'] = uuid_internal
162
+ internal << o
163
+ elsif uuid_external
164
+ o['uuid'] = uuid_external
165
+ external << o
166
+ else
167
+ other << o
168
+ o['uuid'] = ''
169
+ end
166
170
  end
167
- persons['internal'] = internal_persons.uniq
168
- persons['external'] = external_persons.uniq
169
- persons['other'] = other_persons.uniq
170
- persons
171
+ data['internal'] = internal
172
+ data['external'] = external
173
+ data['other'] = other
174
+ data
171
175
  end
172
176
 
173
-
174
-
175
177
  # Date made available
176
178
  #
177
179
  # @return [Hash]
178
180
  def available
179
- data = node('dateMadeAvailable')
180
- Puree::Date.normalise(data)
181
+ temporal_start_date 'dateMadeAvailable'
181
182
  end
182
183
 
183
184
  # Geographical coverage
184
185
  #
185
186
  # @return [Array<String>]
186
187
  def geographical
187
- data = node 'geographicalCoverage'
188
- if !data.nil? && !data.empty?
189
- data = data['localizedString']["__content__"]
190
- data.is_a?(Array) ? data.uniq : data.split(',').map(&:strip).uniq
191
- else
192
- []
188
+ path = '/geographicalCoverage/localizedString'
189
+ xpath_result = xpath_query path
190
+ data = []
191
+ xpath_result.each do |i|
192
+ data << i.text.strip
193
193
  end
194
+ data
194
195
  end
195
196
 
196
197
  # Date of data production
@@ -212,8 +213,8 @@ module Puree
212
213
  #
213
214
  # @return [String]
214
215
  def access
215
- data = node 'openAccessPermission'
216
- !data.nil? && !data.empty? ? data['term']['localizedString']["__content__"].strip : ''
216
+ path = '/openAccessPermission/term/localizedString'
217
+ xpath_query_for_single_value path
217
218
  end
218
219
 
219
220
 
@@ -221,7 +222,7 @@ module Puree
221
222
  #
222
223
  # @return [Array<Hash>]
223
224
  def file
224
- path = '//documents/document'
225
+ path = '/documents/document'
225
226
  xpath_result = xpath_query path
226
227
 
227
228
  docs = []
@@ -254,9 +255,8 @@ module Puree
254
255
  #
255
256
  # @return [String]
256
257
  def doi
257
- path = '//content/doi'
258
- xpath_result = xpath_query path
259
- xpath_result ? xpath_result.text.strip : ''
258
+ path = '/doi'
259
+ xpath_query_for_single_value path
260
260
  end
261
261
 
262
262
  # def state
@@ -280,6 +280,7 @@ module Puree
280
280
  o['keyword'] = keyword
281
281
  o['link'] = link
282
282
  o['organisation'] = organisation
283
+ o['owner'] = owner
283
284
  o['person'] = person
284
285
  o['project'] = project
285
286
  o['production'] = production
@@ -290,12 +291,8 @@ module Puree
290
291
  o
291
292
  end
292
293
 
293
-
294
-
295
294
  private
296
295
 
297
-
298
-
299
296
  # Assembles basic information about a person
300
297
  #
301
298
  # @param generic_data [Hash]
@@ -332,16 +329,26 @@ module Puree
332
329
  #
333
330
  # @return [Hash]
334
331
  def temporal_start_date(start_node)
335
- data = node start_node
336
- !data.nil? && !data.empty? ? Puree::Date.normalise(data) : {}
332
+ path = start_node
333
+ xpath_result = xpath_query path
334
+ o = {}
335
+ o['day'] = xpath_result.xpath('day').text.strip
336
+ o['month'] = xpath_result.xpath('month').text.strip
337
+ o['year'] = xpath_result.xpath('year').text.strip
338
+ Puree::Date.normalise(o)
337
339
  end
338
340
 
339
341
  # Temporal coverage end date
340
342
  #
341
343
  # @return [Hash]
342
344
  def temporal_end_date(end_node)
343
- data = node end_node
344
- !data.nil? && !data.empty? ? Puree::Date.normalise(data) : {}
345
+ path = end_node
346
+ xpath_result = xpath_query path
347
+ o = {}
348
+ o['day'] = xpath_result.xpath('day').text.strip
349
+ o['month'] = xpath_result.xpath('month').text.strip
350
+ o['year'] = xpath_result.xpath('year').text.strip
351
+ Puree::Date.normalise(o)
345
352
  end
346
353
 
347
354
  # Associated type