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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/README.md +16 -339
- data/lib/puree.rb +15 -2
- data/lib/puree/collection.rb +161 -32
- data/lib/puree/configuration.rb +1 -5
- data/lib/puree/dataset.rb +95 -88
- data/lib/puree/download.rb +170 -12
- data/lib/puree/event.rb +16 -11
- data/lib/puree/journal.rb +5 -2
- data/lib/puree/map.rb +13 -2
- data/lib/puree/organisation.rb +16 -15
- data/lib/puree/person.rb +38 -16
- data/lib/puree/project.rb +163 -3
- data/lib/puree/publication.rb +132 -15
- data/lib/puree/publisher.rb +6 -2
- data/lib/puree/resource.rb +95 -70
- data/lib/puree/server.rb +147 -0
- data/lib/puree/version.rb +1 -1
- data/puree.gemspec +2 -2
- data/spec/collection.rb +15 -6
- data/spec/dataset.rb +25 -24
- data/spec/spec_helper.rb +14 -2
- metadata +8 -7
data/lib/puree/collection.rb
CHANGED
@@ -1,25 +1,31 @@
|
|
1
1
|
module Puree
|
2
2
|
|
3
|
-
# Collection
|
3
|
+
# Collection of resources
|
4
4
|
#
|
5
|
-
class Collection
|
5
|
+
class Collection
|
6
6
|
|
7
|
-
# @param
|
7
|
+
# @param resource [Symbol]
|
8
8
|
# @param endpoint [String]
|
9
9
|
# @param optional username [String]
|
10
10
|
# @param optional password [String]
|
11
|
-
|
11
|
+
# @param optional basic_auth [Boolean]
|
12
|
+
def initialize(resource: nil,
|
12
13
|
endpoint: nil,
|
13
14
|
username: nil,
|
14
|
-
password: nil
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
#
|
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
|
-
# @
|
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
|
-
|
40
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
|
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
|
data/lib/puree/configuration.rb
CHANGED
data/lib/puree/dataset.rb
CHANGED
@@ -7,18 +7,21 @@ module Puree
|
|
7
7
|
# @param endpoint [String]
|
8
8
|
# @param optional username [String]
|
9
9
|
# @param optional password [String]
|
10
|
-
|
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 = '
|
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
|
-
#
|
36
|
+
# Owner
|
34
37
|
#
|
35
38
|
# @return [Hash]
|
36
|
-
def
|
37
|
-
path = '
|
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
|
-
|
46
|
+
o
|
44
47
|
end
|
45
48
|
|
46
49
|
# Publisher
|
47
50
|
#
|
48
51
|
# @return [String]
|
49
52
|
def publisher
|
50
|
-
path = '
|
51
|
-
|
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 = '
|
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 = '
|
98
|
-
|
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 = '
|
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 = '
|
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
|
-
|
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 =
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
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
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
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
|
-
|
216
|
-
|
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 = '
|
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 = '
|
258
|
-
|
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
|
-
|
336
|
-
|
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
|
-
|
344
|
-
|
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
|