qa 4.2.0 → 4.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/qa/linked_data_terms_controller.rb +18 -10
- data/app/services/qa/linked_data/graph_service.rb +2 -4
- data/lib/qa/authorities/discogs/discogs_translation.rb +3 -3
- data/lib/qa/authorities/discogs/generic_authority.rb +22 -2
- data/lib/qa/authorities/getty/tgn.rb +1 -1
- data/lib/qa/authorities/linked_data/find_term.rb +17 -2
- data/lib/qa/version.rb +1 -1
- data/spec/controllers/linked_data_terms_controller_spec.rb +18 -0
- data/spec/lib/authorities/discogs/generic_authority_spec.rb +47 -0
- data/spec/lib/authorities/getty/tgn_spec.rb +2 -2
- data/spec/services/linked_data/graph_service_spec.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc8abbc6ff66d5aebf93fc1231c5c9fae0fd1e9a
|
4
|
+
data.tar.gz: 3727fdd6f35c057029047776c8c8ba8ad53810fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efc32a97028b6325586a19b35c11ce1fa6476d34c5b91c0a625b68634fc77c4af9bc665783ecd9e4362dd60d78f10b13d67e98377eb7751a30875dbf777234e4
|
7
|
+
data.tar.gz: 571f1bd47079752a99d59c80115173406068eb1ba23603e07497567c8b3f23927a14a0adce400273c2b5106bfe8dcabc9d2b303a86577aec30e5ebdddc86a96a
|
@@ -59,10 +59,9 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
59
59
|
# get "/show/linked_data/:vocab/:subauthority/:id
|
60
60
|
# @see Qa::Authorities::LinkedData::FindTerm#find
|
61
61
|
def show # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
62
|
-
term = @authority.find(id, subauth: subauthority, language: language, replacements: replacement_params,
|
62
|
+
term = @authority.find(id, subauth: subauthority, language: language, replacements: replacement_params, format: format, performance_data: performance_data?)
|
63
63
|
cors_allow_origin_header(response)
|
64
|
-
|
65
|
-
render json: term, content_type: content_type
|
64
|
+
render json: term, content_type: content_type_for_format
|
66
65
|
rescue Qa::TermNotFound
|
67
66
|
msg = "Term Not Found - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
|
68
67
|
logger.warn msg
|
@@ -90,10 +89,9 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
90
89
|
# get "/fetch/linked_data/:vocab"
|
91
90
|
# @see Qa::Authorities::LinkedData::FindTerm#find
|
92
91
|
def fetch # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
93
|
-
term = @authority.find(uri, subauth: subauthority, language: language, replacements: replacement_params,
|
92
|
+
term = @authority.find(uri, subauth: subauthority, language: language, replacements: replacement_params, format: format, performance_data: performance_data?)
|
94
93
|
cors_allow_origin_header(response)
|
95
|
-
|
96
|
-
render json: term, content_type: content_type
|
94
|
+
render json: term, content_type: content_type_for_format
|
97
95
|
rescue Qa::TermNotFound
|
98
96
|
msg = "Term Not Found - Fetch term #{uri} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
|
99
97
|
logger.warn msg
|
@@ -217,22 +215,32 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
217
215
|
end
|
218
216
|
|
219
217
|
def jsonld?
|
220
|
-
format.casecmp('jsonld')
|
218
|
+
format.casecmp?('jsonld')
|
219
|
+
end
|
220
|
+
|
221
|
+
def n3?
|
222
|
+
format.casecmp?('n3')
|
223
|
+
end
|
224
|
+
|
225
|
+
def content_type_for_format
|
226
|
+
return 'application/ld+json' if jsonld?
|
227
|
+
return 'text/n3' if n3?
|
228
|
+
'application/json'
|
221
229
|
end
|
222
230
|
|
223
231
|
def context?
|
224
232
|
context = params.fetch(:context, 'false')
|
225
|
-
context.casecmp('true')
|
233
|
+
context.casecmp?('true')
|
226
234
|
end
|
227
235
|
|
228
236
|
def details?
|
229
237
|
details = params.fetch(:details, 'false')
|
230
|
-
details.casecmp('true')
|
238
|
+
details.casecmp?('true')
|
231
239
|
end
|
232
240
|
|
233
241
|
def performance_data?
|
234
242
|
performance_data = params.fetch(:performance_data, 'false')
|
235
|
-
performance_data.casecmp('true')
|
243
|
+
performance_data.casecmp?('true')
|
236
244
|
end
|
237
245
|
|
238
246
|
def validate_auth_reload_token
|
@@ -106,12 +106,10 @@ module Qa
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
+
# process ioerror_code from RDF::Graph.load whether the code is in parentheses (i.e. "... (404)"), or not (i.e. "... 404")
|
109
110
|
def ioerror_code(e)
|
110
111
|
msg = e.message
|
111
|
-
|
112
|
-
a = msg.size - 4
|
113
|
-
z = msg.size - 2
|
114
|
-
msg[a..z]
|
112
|
+
msg[/(\(?)(\d\d\d)(\)?)$/, 2]
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
@@ -11,14 +11,14 @@ module Qa::Authorities
|
|
11
11
|
# to the URIs of corresponding objects in the Library of Congress vocabulary.
|
12
12
|
# @param [Hash] the http response from discogs
|
13
13
|
# @param [String] the subauthority
|
14
|
-
# @return [Array] jsonld
|
15
|
-
def build_graph(response, subauthority = "")
|
14
|
+
# @return [Array, String] requested RDF serialzation (supports: jsonld Array, n3 String)
|
15
|
+
def build_graph(response, subauthority = "", format: :jsonld)
|
16
16
|
graph = RDF::Graph.new
|
17
17
|
|
18
18
|
rdf_statements = compile_rdf_statements(response, subauthority)
|
19
19
|
graph.insert_statements(rdf_statements)
|
20
20
|
|
21
|
-
graph.dump(
|
21
|
+
graph.dump(format, standard_prefixes: true)
|
22
22
|
end
|
23
23
|
|
24
24
|
# @param [Hash] the http response from discogs
|
@@ -35,10 +35,12 @@ module Qa::Authorities
|
|
35
35
|
#
|
36
36
|
# @param [String] the Discogs id of the selected item
|
37
37
|
# @param [Class] QA::TermsController
|
38
|
-
# @return
|
38
|
+
# @return results in requested format (supports: json, jsonld, n3)
|
39
39
|
def find(id, tc)
|
40
40
|
response = tc.params["subauthority"].include?("all") ? fetch_discogs_results(id) : json(find_url(id, tc.params["subauthority"]))
|
41
|
-
return
|
41
|
+
return response if response["message"].present?
|
42
|
+
return build_graph(response, format: :jsonld) if jsonld?(tc)
|
43
|
+
return build_graph(response, format: :n3) if n3?(tc)
|
42
44
|
response
|
43
45
|
end
|
44
46
|
|
@@ -147,5 +149,23 @@ module Qa::Authorities
|
|
147
149
|
def get_context_for_array(item)
|
148
150
|
item.present? ? item : [""]
|
149
151
|
end
|
152
|
+
|
153
|
+
def format(tc)
|
154
|
+
return 'json' unless tc.params.key?('format')
|
155
|
+
return 'json' if tc.params['format'].blank?
|
156
|
+
tc.params['format']
|
157
|
+
end
|
158
|
+
|
159
|
+
def jsonld?(tc)
|
160
|
+
format(tc).casecmp?('jsonld')
|
161
|
+
end
|
162
|
+
|
163
|
+
def n3?(tc)
|
164
|
+
format(tc).casecmp?('n3')
|
165
|
+
end
|
166
|
+
|
167
|
+
def graph_format?(tc)
|
168
|
+
jsonld?(tc) || n3?(tc)
|
169
|
+
end
|
150
170
|
end
|
151
171
|
end
|
@@ -28,7 +28,7 @@ module Qa::Authorities
|
|
28
28
|
end
|
29
29
|
%(SELECT DISTINCT ?s ?name ?par {
|
30
30
|
?s a skos:Concept; luc:term "#{search}";
|
31
|
-
skos:inScheme <http://vocab.getty.edu/
|
31
|
+
skos:inScheme <http://vocab.getty.edu/tgn/> ;
|
32
32
|
gvp:prefLabelGVP [skosxl:literalForm ?name] ;
|
33
33
|
gvp:parentString ?par .
|
34
34
|
FILTER #{ex} .
|
@@ -39,12 +39,20 @@ module Qa::Authorities
|
|
39
39
|
# "http://schema.org/name":["Cornell University","Ithaca (N.Y.). Cornell University"],
|
40
40
|
# "http://www.w3.org/2004/02/skos/core#altLabel":["Ithaca (N.Y.). Cornell University"],
|
41
41
|
# "http://schema.org/sameAs":["http://id.loc.gov/authorities/names/n79021621","https://viaf.org/viaf/126293486"] } }
|
42
|
-
def find(id, language: nil, replacements: {}, subauth: nil, jsonld: false, performance_data: false) # rubocop:disable Metrics/ParameterLists
|
42
|
+
def find(id, language: nil, replacements: {}, subauth: nil, format: nil, jsonld: false, performance_data: false) # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
43
|
+
# TODO: When jsonld parameter is removed, the format parameter should default to 'json'. Not making this change now for backward compatibility of the default for jsonld parameter.
|
43
44
|
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data term sub-authority #{subauth}" unless subauth.nil? || term_subauthority?(subauth)
|
44
45
|
@language = language_service.preferred_language(user_language: language, authority_language: term_config.term_language)
|
45
46
|
@id = id
|
46
47
|
@performance_data = performance_data
|
47
|
-
@
|
48
|
+
@format = format
|
49
|
+
@jsonld = jsonld if @format.blank?
|
50
|
+
if jsonld
|
51
|
+
Qa.deprecation_warning(
|
52
|
+
in_msg: 'Qa::Authorities::LinkedData::FindTerm',
|
53
|
+
msg: "jsonld parameter to find method is deprecated; use `format: 'jsonld'` instead"
|
54
|
+
)
|
55
|
+
end
|
48
56
|
url = authority_service.build_url(action_config: term_config, action: :term, action_request: normalize_id, substitutions: replacements, subauthority: subauth, language: @language)
|
49
57
|
Rails.logger.info "QA Linked Data term url: #{url}"
|
50
58
|
load_graph(url: url)
|
@@ -80,6 +88,7 @@ module Qa::Authorities
|
|
80
88
|
def perform_normalization
|
81
89
|
return "{}" unless full_graph.size.positive?
|
82
90
|
return full_graph.dump(:jsonld, standard_prefixes: true) if jsonld?
|
91
|
+
return full_graph.dump(:n3, standard_prefixes: true) if n3?
|
83
92
|
|
84
93
|
filter_graph
|
85
94
|
extract_uri
|
@@ -182,10 +191,16 @@ module Qa::Authorities
|
|
182
191
|
opt_ldpaths.delete_if { |_k, v| v.blank? }
|
183
192
|
end
|
184
193
|
|
194
|
+
# Give precedent to format parameter over jsonld parameter. NOTE: jsonld parameter for find method is deprecated.
|
185
195
|
def jsonld?
|
196
|
+
return @format.casecmp?('jsonld') if @format
|
186
197
|
@jsonld == true
|
187
198
|
end
|
188
199
|
|
200
|
+
def n3?
|
201
|
+
@format && @format.casecmp?('n3')
|
202
|
+
end
|
203
|
+
|
189
204
|
def performance_data?
|
190
205
|
@performance_data == true && !jsonld?
|
191
206
|
end
|
data/lib/qa/version.rb
CHANGED
@@ -425,6 +425,15 @@ describe Qa::LinkedDataTermsController, type: :controller do
|
|
425
425
|
expect(JSON.parse(response.body).keys).to match_array ["@context", "@graph"]
|
426
426
|
end
|
427
427
|
end
|
428
|
+
|
429
|
+
context 'and it was requested as n3' do
|
430
|
+
it 'succeeds and returns term data as n3 content type' do
|
431
|
+
get :show, params: { id: '530369', vocab: 'OCLC_FAST', format: 'n3' }
|
432
|
+
expect(response).to be_successful
|
433
|
+
expect(response.content_type).to eq 'text/n3'
|
434
|
+
expect(response.body).to start_with "@prefix"
|
435
|
+
end
|
436
|
+
end
|
428
437
|
end
|
429
438
|
|
430
439
|
context 'when cors headers are enabled' do
|
@@ -587,6 +596,15 @@ describe Qa::LinkedDataTermsController, type: :controller do
|
|
587
596
|
end
|
588
597
|
end
|
589
598
|
|
599
|
+
context 'and it was requested as n3' do
|
600
|
+
it 'succeeds and returns term data as n3 content type' do
|
601
|
+
get :fetch, params: { uri: 'http://id.worldcat.org/fast/530369', vocab: 'LOD_TERM_URI_PARAM_CONFIG', format: 'n3' }
|
602
|
+
expect(response).to be_successful
|
603
|
+
expect(response.content_type).to eq 'text/n3'
|
604
|
+
expect(response.body).to start_with "@prefix"
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
590
608
|
context 'blank nodes not included in predicates list' do
|
591
609
|
before do
|
592
610
|
stub_request(:get, 'http://localhost/test_default/term?uri=http://id.worldcat.org/fast/530369wbn')
|
@@ -136,6 +136,28 @@ describe Qa::Authorities::Discogs::GenericAuthority do
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
+
context "n3 format and subauthority master" do
|
140
|
+
let(:tc) { instance_double(Qa::TermsController) }
|
141
|
+
let :results do
|
142
|
+
authority.find("950011", tc)
|
143
|
+
end
|
144
|
+
before do
|
145
|
+
allow(Qa::TermsController).to receive(:new).and_return(tc)
|
146
|
+
allow(tc).to receive(:params).and_return('format' => "n3", 'subauthority' => "master")
|
147
|
+
end
|
148
|
+
|
149
|
+
it "returns the Discogs data converted to n3 for a given id" do
|
150
|
+
expect(results).to start_with "@prefix"
|
151
|
+
expect(results).to include("Blue Moon / You Go To My Head")
|
152
|
+
expect(results).to include("Billie Holiday And Her Orchestra")
|
153
|
+
expect(results).to include("Haven Gillespie")
|
154
|
+
expect(results).to include("1952")
|
155
|
+
expect(results).to include("Jazz")
|
156
|
+
expect(results).to include("Barney Kessel")
|
157
|
+
expect(results).to include("Guitar")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
139
161
|
context "json-ld format and subauthority all" do
|
140
162
|
let(:tc) { instance_double(Qa::TermsController) }
|
141
163
|
let :results do
|
@@ -161,6 +183,31 @@ describe Qa::Authorities::Discogs::GenericAuthority do
|
|
161
183
|
expect(results).to include("1952")
|
162
184
|
end
|
163
185
|
end
|
186
|
+
|
187
|
+
context "n3 format and subauthority all" do
|
188
|
+
let(:tc) { instance_double(Qa::TermsController) }
|
189
|
+
let :results do
|
190
|
+
authority.find("7143179", tc)
|
191
|
+
end
|
192
|
+
before do
|
193
|
+
allow(Qa::TermsController).to receive(:new).and_return(tc)
|
194
|
+
allow(tc).to receive(:params).and_return('format' => "n3", 'subauthority' => "all")
|
195
|
+
end
|
196
|
+
|
197
|
+
it "returns the Discogs data converted to n3 for a given id" do
|
198
|
+
expect(results).to start_with "@prefix"
|
199
|
+
expect(results).to include("You Go To My Head")
|
200
|
+
expect(results).to include("Rodgers & Hart")
|
201
|
+
expect(results).to include("Ray Brown")
|
202
|
+
expect(results).to include("1952")
|
203
|
+
expect(results).to include("Single")
|
204
|
+
expect(results).to include("mono")
|
205
|
+
expect(results).to include("45 RPM")
|
206
|
+
expect(results).to include("Vinyl")
|
207
|
+
expect(results).to include("http://id.loc.gov/vocabulary/carriers/sd")
|
208
|
+
expect(results).to include("1952")
|
209
|
+
end
|
210
|
+
end
|
164
211
|
end
|
165
212
|
end
|
166
213
|
|
@@ -82,13 +82,13 @@ describe Qa::Authorities::Getty::TGN do
|
|
82
82
|
context "using a single subject term" do
|
83
83
|
subject { authority.sparql('search_term') }
|
84
84
|
it {
|
85
|
-
is_expected.to eq %(SELECT DISTINCT ?s ?name ?par { ?s a skos:Concept; luc:term "search_term"; skos:inScheme <http://vocab.getty.edu/
|
85
|
+
is_expected.to eq %(SELECT DISTINCT ?s ?name ?par { ?s a skos:Concept; luc:term "search_term"; skos:inScheme <http://vocab.getty.edu/tgn/> ; gvp:prefLabelGVP [skosxl:literalForm ?name] ; gvp:parentString ?par . FILTER regex(?name, "search_term", "i") . } ORDER BY ?name ASC(?par))
|
86
86
|
}
|
87
87
|
end
|
88
88
|
context "using a two subject terms" do
|
89
89
|
subject { authority.sparql('search term') }
|
90
90
|
it {
|
91
|
-
is_expected.to eq %(SELECT DISTINCT ?s ?name ?par { ?s a skos:Concept; luc:term "search term"; skos:inScheme <http://vocab.getty.edu/
|
91
|
+
is_expected.to eq %(SELECT DISTINCT ?s ?name ?par { ?s a skos:Concept; luc:term "search term"; skos:inScheme <http://vocab.getty.edu/tgn/> ; gvp:prefLabelGVP [skosxl:literalForm ?name] ; gvp:parentString ?par . FILTER ((regex(?name, "search", "i") || regex(?alt, "search", "i")) && (regex(?name, "term", "i") || regex(?alt, "term", "i"))) . } ORDER BY ?name ASC(?par))
|
92
92
|
}
|
93
93
|
end
|
94
94
|
end
|
@@ -66,6 +66,7 @@ RSpec.describe Qa::LinkedData::GraphService do
|
|
66
66
|
subject { described_class.load_graph(url: url) }
|
67
67
|
|
68
68
|
let(:url) { 'http://experimental.worldcat.org/fast/search?maximumRecords=3&query=cql.any%20all%20%22cornell%22&sortKeys=usage' }
|
69
|
+
let(:regurl) { 'http:\/\/experimental.worldcat.org\/fast\/search\?maximumRecords=3&query=cql.any%20all%20%22cornell%22&sortKeys=usage' }
|
69
70
|
let(:uri) { URI(url) }
|
70
71
|
|
71
72
|
before do
|
@@ -74,7 +75,7 @@ RSpec.describe Qa::LinkedData::GraphService do
|
|
74
75
|
end
|
75
76
|
|
76
77
|
it 'raises error' do
|
77
|
-
expect { subject }.to raise_error(Qa::ServiceError,
|
78
|
+
expect { subject }.to raise_error(Qa::ServiceError, /Unknown error for #{uri.hostname} on port #{uri.port}. Try again later. \(Cause - <#{regurl}>: \(?504\)?\)/)
|
78
79
|
end
|
79
80
|
end
|
80
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.
|
4
|
+
version: 4.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Anderson
|
@@ -16,7 +16,7 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date: 2019-
|
19
|
+
date: 2019-08-08 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: activerecord-import
|