puree 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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