qa 2.0.0 → 2.3.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 +5 -5
- data/README.md +54 -6
- data/app/controllers/qa/application_controller.rb +24 -0
- data/app/controllers/qa/linked_data_terms_controller.rb +116 -51
- data/app/controllers/qa/terms_controller.rb +7 -2
- data/app/models/qa/mesh_tree.rb +5 -9
- data/app/models/qa/subject_mesh_term.rb +2 -7
- data/config/authorities/linked_data/agrovoc.json +8 -1
- data/config/initializers/linked_data_authorities.rb +1 -17
- data/config/routes.rb +11 -0
- data/lib/generators/qa/apidoc/USAGE +11 -0
- data/lib/generators/qa/apidoc/apidoc_generator.rb +22 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/apidoc.json +1322 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/favicon-16x16.png +0 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/favicon-32x32.png +0 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/index.html +61 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/oauth2-redirect.html +67 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-bundle.js +93 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-bundle.js.map +1 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-standalone-preset.js +14 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-standalone-preset.js.map +1 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.css +3 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.css.map +1 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.js +9 -0
- data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.js.map +1 -0
- data/lib/generators/qa/install/install_generator.rb +11 -0
- data/lib/generators/qa/install/templates/config/initializers/qa.rb +13 -0
- data/lib/generators/qa/local/tables/mysql/mysql_generator.rb +1 -1
- data/lib/generators/qa/local/tables/tables_generator.rb +1 -1
- data/lib/qa.rb +16 -0
- data/lib/qa/authorities/assign_fast_subauthority.rb +3 -3
- data/lib/qa/authorities/getty/aat.rb +13 -6
- data/lib/qa/authorities/getty/tgn.rb +11 -22
- data/lib/qa/authorities/getty/ulan.rb +13 -16
- data/lib/qa/authorities/linked_data.rb +1 -0
- data/lib/qa/authorities/linked_data/authority_service.rb +47 -0
- data/lib/qa/authorities/linked_data/config.rb +9 -3
- data/lib/qa/authorities/linked_data/config/search_config.rb +16 -2
- data/lib/qa/authorities/linked_data/config/term_config.rb +17 -3
- data/lib/qa/authorities/linked_data/find_term.rb +4 -3
- data/lib/qa/authorities/linked_data/generic_authority.rb +8 -1
- data/lib/qa/authorities/linked_data/rdf_helper.rb +15 -0
- data/lib/qa/authorities/linked_data/search_query.rb +19 -3
- data/lib/qa/authorities/loc/generic_authority.rb +2 -2
- data/lib/qa/authorities/loc_subauthority.rb +2 -2
- data/lib/qa/authorities/local.rb +2 -4
- data/lib/qa/authorities/local/file_based_authority.rb +1 -1
- data/lib/qa/authorities/local/mysql_table_based_authority.rb +11 -2
- data/lib/qa/authorities/local/table_based_authority.rb +2 -1
- data/lib/qa/authorities/mesh_tools/mesh_data_parser.rb +1 -1
- data/lib/qa/authorities/mesh_tools/mesh_importer.rb +1 -1
- data/lib/qa/authorities/oclcts/generic_oclc_authority.rb +1 -3
- data/lib/qa/configuration.rb +34 -0
- data/lib/qa/version.rb +1 -1
- data/lib/tasks/mesh.rake +3 -3
- data/spec/controllers/linked_data_terms_controller_spec.rb +247 -18
- data/spec/controllers/terms_controller_spec.rb +87 -12
- data/spec/fixtures/authorities/linked_data/lod_encoding_config.json +91 -0
- data/spec/fixtures/authorities/linked_data/lod_term_id_param_config.json +27 -0
- data/spec/fixtures/authorities/linked_data/lod_term_uri_param_config.json +27 -0
- data/spec/fixtures/{lexvo_snippet.rdf → lexvo_snippet.rdf.xml} +1 -0
- data/spec/lib/authorities/assign_fast_spec.rb +3 -1
- data/spec/lib/authorities/file_based_authority_spec.rb +19 -11
- data/spec/lib/authorities/geonames_spec.rb +3 -3
- data/spec/lib/authorities/getty/aat_spec.rb +14 -8
- data/spec/lib/authorities/getty/tgn_spec.rb +8 -15
- data/spec/lib/authorities/getty/ulan_spec.rb +8 -6
- data/spec/lib/authorities/getty_spec.rb +2 -1
- data/spec/lib/authorities/linked_data/authority_service_spec.rb +47 -0
- data/spec/lib/authorities/linked_data/generic_authority_spec.rb +56 -14
- data/spec/lib/authorities/linked_data/search_config_spec.rb +33 -19
- data/spec/lib/authorities/linked_data/search_query_spec.rb +67 -15
- data/spec/lib/authorities/linked_data/term_config_spec.rb +34 -20
- data/spec/lib/authorities/loc_spec.rb +9 -9
- data/spec/lib/authorities/local_spec.rb +7 -8
- data/spec/lib/authorities/oclcts_spec.rb +27 -20
- data/spec/lib/authorities/table_based_authority_spec.rb +5 -3
- data/spec/lib/authorities_loc_subauthorities.rb +2 -2
- data/spec/lib/configuration_spec.rb +58 -0
- data/spec/lib/mesh_data_parser_spec.rb +2 -0
- data/spec/lib/services/rdf_authority_parser_spec.rb +1 -1
- data/spec/lib/tasks/mesh.rake_spec.rb +13 -12
- data/spec/models/subject_mesh_term_spec.rb +2 -0
- data/spec/requests/cors_headers_spec.rb +118 -0
- data/spec/spec_helper.rb +2 -2
- metadata +167 -137
|
@@ -11,29 +11,26 @@ module Qa::Authorities
|
|
|
11
11
|
"http://vocab.getty.edu/sparql.json?query=#{URI.escape(sparql(q)).gsub('&', '%26')}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def sparql(q)
|
|
14
|
+
def sparql(q) # rubocop:disable Metrics/MethodLength
|
|
15
15
|
search = untaint(q)
|
|
16
16
|
# if more than one term is supplied, check both preferred and alt labels
|
|
17
17
|
if search.include?(' ')
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ex += "regex(CONCAT(?name, ' ', ?alt), \"#{i}\",\"i\" ) && "
|
|
18
|
+
clauses = search.split(' ').collect do |i|
|
|
19
|
+
%((regex(?name, "#{i}", "i") || regex(?alt, "#{i}", "i")))
|
|
21
20
|
end
|
|
22
|
-
ex =
|
|
23
|
-
ex += ")"
|
|
21
|
+
ex = "(#{clauses.join(' && ')})"
|
|
24
22
|
else
|
|
25
|
-
ex =
|
|
23
|
+
ex = %(regex(?name, "#{search}", "i"))
|
|
26
24
|
end
|
|
27
25
|
# The full text index matches on fields besides the term, so we filter to ensure the match is in the term.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
sparql
|
|
26
|
+
%(SELECT DISTINCT ?s ?name ?bio {
|
|
27
|
+
?s a skos:Concept; luc:term "#{search}";
|
|
28
|
+
skos:inScheme <http://vocab.getty.edu/ulan/> ;
|
|
29
|
+
gvp:prefLabelGVP [skosxl:literalForm ?name] ;
|
|
30
|
+
foaf:focus/gvp:biographyPreferred [schema:description ?bio] ;
|
|
31
|
+
skos:altLabel ?alt .
|
|
32
|
+
FILTER #{ex} .
|
|
33
|
+
} ORDER BY ?name).gsub(/[\s\n]+/, " ")
|
|
37
34
|
end
|
|
38
35
|
|
|
39
36
|
def untaint(q)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# This module has the primary QA search method. It also includes methods to process the linked data results and convert
|
|
2
|
+
# them into the expected QA json results format.
|
|
3
|
+
module Qa::Authorities
|
|
4
|
+
module LinkedData
|
|
5
|
+
class AuthorityService
|
|
6
|
+
# Load or reload the linked data configuration files
|
|
7
|
+
def self.load_authorities
|
|
8
|
+
auth_cfg = {}
|
|
9
|
+
# load QA configured linked data authorities
|
|
10
|
+
Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
|
11
|
+
auth = File.basename(fn, '.json').upcase.to_sym
|
|
12
|
+
json = File.read(File.expand_path(fn, __FILE__))
|
|
13
|
+
cfg = JSON.parse(json).deep_symbolize_keys
|
|
14
|
+
auth_cfg[auth] = cfg
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# load app configured linked data authorities and overrides
|
|
18
|
+
Dir[Rails.root.join('config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
|
19
|
+
auth = File.basename(fn, '.json').upcase.to_sym
|
|
20
|
+
json = File.read(File.expand_path(fn, __FILE__))
|
|
21
|
+
cfg = JSON.parse(json).deep_symbolize_keys
|
|
22
|
+
auth_cfg[auth] = cfg
|
|
23
|
+
end
|
|
24
|
+
Qa.config.linked_data_authority_configs = auth_cfg
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get the list of names of the loaded authorities
|
|
28
|
+
# @return [Array<String>] all loaded authority configurations
|
|
29
|
+
def self.authority_configs
|
|
30
|
+
Qa.config.linked_data_authority_configs
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get the configuration for an authority
|
|
34
|
+
# @param [String] name of the authority
|
|
35
|
+
# @return [Array<String>] configuration for the specified authority
|
|
36
|
+
def self.authority_config(authname)
|
|
37
|
+
authority_configs[authname]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Get the list of names of the loaded authorities
|
|
41
|
+
# @return [Array<String>] names of the authority config files that are currently loaded
|
|
42
|
+
def self.authority_names
|
|
43
|
+
authority_configs.keys.sort
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'qa/authorities/linked_data/config/term_config'.freeze
|
|
2
2
|
require 'qa/authorities/linked_data/config/search_config'.freeze
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'erb'
|
|
4
5
|
|
|
5
6
|
# Provide attr_reader methods for linked data authority configurations. Some default configurations are provided for several
|
|
6
7
|
# linked data authorities and can be found at /config/authorities/linked_data. You can add configurations for new authorities by
|
|
@@ -17,6 +18,10 @@ require 'json'
|
|
|
17
18
|
module Qa::Authorities
|
|
18
19
|
module LinkedData
|
|
19
20
|
class Config
|
|
21
|
+
class << self
|
|
22
|
+
include ERB::Util
|
|
23
|
+
end
|
|
24
|
+
|
|
20
25
|
attr_reader :authority_name
|
|
21
26
|
attr_reader :authority_config
|
|
22
27
|
|
|
@@ -39,7 +44,7 @@ module Qa::Authorities
|
|
|
39
44
|
# Return the full configuration for an authority
|
|
40
45
|
# @return [String] the authority configuration
|
|
41
46
|
def auth_config
|
|
42
|
-
@authority_config ||=
|
|
47
|
+
@authority_config ||= Qa::Authorities::LinkedData::AuthorityService.authority_config(@authority_name)
|
|
43
48
|
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data authority '#{@authority_name}'" if @authority_config.nil?
|
|
44
49
|
@authority_config
|
|
45
50
|
end
|
|
@@ -56,7 +61,8 @@ module Qa::Authorities
|
|
|
56
61
|
pred_uri
|
|
57
62
|
end
|
|
58
63
|
|
|
59
|
-
def self.replace_pattern(url, pattern, value)
|
|
64
|
+
def self.replace_pattern(url, pattern, value, encode = false)
|
|
65
|
+
value = url_encode(value).gsub(".", "%2E") if encode
|
|
60
66
|
url.gsub("{?#{pattern}}", value)
|
|
61
67
|
end
|
|
62
68
|
|
|
@@ -71,7 +77,7 @@ module Qa::Authorities
|
|
|
71
77
|
config.each do |param_key, rep_pattern|
|
|
72
78
|
s_param_key = param_key.to_s
|
|
73
79
|
value = replacements[param_key] || replacements[s_param_key] || rep_pattern[:default]
|
|
74
|
-
url = replace_pattern(url, param_key, value)
|
|
80
|
+
url = replace_pattern(url, param_key, value, rep_pattern[:encode])
|
|
75
81
|
end
|
|
76
82
|
url
|
|
77
83
|
end
|
|
@@ -95,12 +95,26 @@ module Qa::Authorities
|
|
|
95
95
|
search_config.fetch(:qa_replacement_patterns)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
# Should the replacement pattern be encoded?
|
|
99
|
+
# @return [Boolean] true, if the pattern should be encoded; otherwise, false
|
|
100
|
+
def qa_replacement_encoded?(pattern_key)
|
|
101
|
+
map_key = qa_replacement_patterns[pattern_key].to_sym
|
|
102
|
+
replacement_encoded? map_key
|
|
103
|
+
end
|
|
104
|
+
|
|
98
105
|
# Are there replacement parameters configured for search query?
|
|
99
106
|
# @return [True|False] true if there are replacement parameters configured for search query; otherwise, false
|
|
100
107
|
def replacements?
|
|
101
108
|
replacement_count.positive?
|
|
102
109
|
end
|
|
103
110
|
|
|
111
|
+
# Should the replacement parameter be encoded?
|
|
112
|
+
# @return [True|False] true if the replacement parameter should be encoded; otherwise, false
|
|
113
|
+
def replacement_encoded?(map_key)
|
|
114
|
+
return false unless url_mappings[map_key].key? :encode
|
|
115
|
+
url_mappings[map_key][:encode]
|
|
116
|
+
end
|
|
117
|
+
|
|
104
118
|
# Return the number of possible replacement values to make in the search URL
|
|
105
119
|
# @return [Integer] the configured number of possible replacements in the search url
|
|
106
120
|
def replacement_count
|
|
@@ -159,8 +173,8 @@ module Qa::Authorities
|
|
|
159
173
|
# @return [String] the search encoded url
|
|
160
174
|
def url_with_replacements(query, sub_auth = nil, search_replacements = {})
|
|
161
175
|
return nil unless supports_search?
|
|
162
|
-
sub_auth = sub_auth.to_sym if sub_auth.
|
|
163
|
-
url = Config.replace_pattern(url_template, qa_replacement_patterns[:query], query)
|
|
176
|
+
sub_auth = sub_auth.to_sym if sub_auth.present?
|
|
177
|
+
url = Config.replace_pattern(url_template, qa_replacement_patterns[:query], query, qa_replacement_encoded?(:query))
|
|
164
178
|
url = Config.process_subauthority(url, subauthority_replacement_pattern, subauthorities, sub_auth) if subauthorities?
|
|
165
179
|
url = Config.apply_replacements(url, replacements, search_replacements) if replacements?
|
|
166
180
|
url
|
|
@@ -112,12 +112,26 @@ module Qa::Authorities
|
|
|
112
112
|
Config.config_value(term_config, :qa_replacement_patterns)
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
# Should the replacement pattern be encoded?
|
|
116
|
+
# @return [Boolean] true, if the pattern should be encoded; otherwise, false
|
|
117
|
+
def term_qa_replacement_encoded?(pattern_key)
|
|
118
|
+
map_key = term_qa_replacement_patterns[pattern_key].to_sym
|
|
119
|
+
term_replacement_encoded? map_key
|
|
120
|
+
end
|
|
121
|
+
|
|
115
122
|
# Are there replacement parameters configured for term fetch?
|
|
116
|
-
# @return [
|
|
123
|
+
# @return [Boolean] true if there are replacement parameters configured for term fetch; otherwise, false
|
|
117
124
|
def term_replacements?
|
|
118
125
|
term_replacement_count.positive?
|
|
119
126
|
end
|
|
120
127
|
|
|
128
|
+
# Should the replacement parameter be encoded?
|
|
129
|
+
# @return [Boolean] true if the replacement parameter should be encoded; otherwise, false
|
|
130
|
+
def term_replacement_encoded?(map_key)
|
|
131
|
+
return false unless term_url_mappings[map_key].key? :encode
|
|
132
|
+
term_url_mappings[map_key][:encode]
|
|
133
|
+
end
|
|
134
|
+
|
|
121
135
|
# Return the number of possible replacement values to make in the term URL
|
|
122
136
|
# @return [Integer] the configured number of possible replacements in the term url
|
|
123
137
|
def term_replacement_count
|
|
@@ -129,7 +143,7 @@ module Qa::Authorities
|
|
|
129
143
|
def term_replacements
|
|
130
144
|
return @term_replacements unless @term_replacements.nil?
|
|
131
145
|
@term_replacements = {}
|
|
132
|
-
@term_replacements = term_url_mappings.select { |k, _v| !term_qa_replacement_patterns.
|
|
146
|
+
@term_replacements = term_url_mappings.select { |k, _v| !term_qa_replacement_patterns.value?(k.to_s) } unless term_config.nil? || term_url_mappings.nil?
|
|
133
147
|
@term_replacements
|
|
134
148
|
end
|
|
135
149
|
|
|
@@ -176,7 +190,7 @@ module Qa::Authorities
|
|
|
176
190
|
def term_url_with_replacements(id, sub_auth = nil, replacements = {})
|
|
177
191
|
return nil unless supports_term?
|
|
178
192
|
sub_auth = sub_auth.to_sym if sub_auth.is_a? String
|
|
179
|
-
url = Config.replace_pattern(term_url_template, term_qa_replacement_patterns[:term_id], id)
|
|
193
|
+
url = Config.replace_pattern(term_url_template, term_qa_replacement_patterns[:term_id], id, term_qa_replacement_encoded?(:term_id))
|
|
180
194
|
url = Config.process_subauthority(url, term_subauthority_replacement_pattern, term_subauthorities, sub_auth) if term_subauthorities?
|
|
181
195
|
url = Config.apply_replacements(url, term_replacements, replacements) if term_replacements?
|
|
182
196
|
url
|
|
@@ -33,13 +33,14 @@ module Qa::Authorities
|
|
|
33
33
|
# "http://schema.org/name":["Cornell University","Ithaca (N.Y.). Cornell University"],
|
|
34
34
|
# "http://www.w3.org/2004/02/skos/core#altLabel":["Ithaca (N.Y.). Cornell University"],
|
|
35
35
|
# "http://schema.org/sameAs":["http://id.loc.gov/authorities/names/n79021621","https://viaf.org/viaf/126293486"] } }
|
|
36
|
-
def find(id, language: nil, replacements: {}, subauth: nil)
|
|
36
|
+
def find(id, language: nil, replacements: {}, subauth: nil, jsonld: false)
|
|
37
37
|
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data term sub-authority #{subauth}" unless subauth.nil? || term_subauthority?(subauth)
|
|
38
38
|
language ||= term_config.term_language
|
|
39
39
|
url = term_config.term_url_with_replacements(id, subauth, replacements)
|
|
40
40
|
Rails.logger.info "QA Linked Data term url: #{url}"
|
|
41
41
|
graph = get_linked_data(url)
|
|
42
42
|
return "{}" unless graph.size.positive?
|
|
43
|
+
return graph.dump(:jsonld, standard_prefixes: true) if jsonld
|
|
43
44
|
parse_term_authority_response(id, graph, language)
|
|
44
45
|
end
|
|
45
46
|
|
|
@@ -76,7 +77,7 @@ module Qa::Authorities
|
|
|
76
77
|
preds
|
|
77
78
|
end
|
|
78
79
|
|
|
79
|
-
def consolidate_term_results(results)
|
|
80
|
+
def consolidate_term_results(results) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize # TODO: Explore a way to simplify
|
|
80
81
|
consolidated_results = {}
|
|
81
82
|
results.each do |statement|
|
|
82
83
|
stmt_hash = statement.to_h
|
|
@@ -123,7 +124,7 @@ module Qa::Authorities
|
|
|
123
124
|
json_results.first
|
|
124
125
|
end
|
|
125
126
|
|
|
126
|
-
def predicates_with_subject_uri(graph, expected_uri)
|
|
127
|
+
def predicates_with_subject_uri(graph, expected_uri) # rubocop:disable Metrics/MethodLength
|
|
127
128
|
predicates_hash = {}
|
|
128
129
|
graph.statements.each do |st|
|
|
129
130
|
subj = st.subject.to_s
|
|
@@ -22,7 +22,13 @@ module Qa::Authorities
|
|
|
22
22
|
@auth_config = Qa::Authorities::LinkedData::Config.new(auth_name)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
def reload_authorities
|
|
26
|
+
@authorities_service.load_authorities
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authorities_service
|
|
30
|
+
@authorities_service ||= Qa::Authorities::LinkedData::AuthorityService
|
|
31
|
+
end
|
|
26
32
|
|
|
27
33
|
def search_service
|
|
28
34
|
@search_service ||= Qa::Authorities::LinkedData::SearchQuery.new(search_config)
|
|
@@ -34,6 +40,7 @@ module Qa::Authorities
|
|
|
34
40
|
|
|
35
41
|
delegate :search, to: :search_service
|
|
36
42
|
delegate :find, to: :item_service
|
|
43
|
+
delegate :load_authorities, :authority_names, to: :authorities_service
|
|
37
44
|
|
|
38
45
|
private
|
|
39
46
|
|
|
@@ -57,6 +57,10 @@ module Qa::Authorities
|
|
|
57
57
|
msg[a..z]
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# Filter a graph to the specified languages
|
|
61
|
+
# @param [RDF::Graph] the graph to be filtered.
|
|
62
|
+
# @param [String | Symbol | Array<String|Symbol>] language for filtering graph (e.g. "en" or :en or ["en", "fr"] or [:en, :fr])
|
|
63
|
+
# @returns [RDF::Graph] graph of linked data filtered on the specified languages
|
|
60
64
|
def filter_language(graph, language)
|
|
61
65
|
language = normalize_language(language)
|
|
62
66
|
return graph if language.nil?
|
|
@@ -66,6 +70,17 @@ module Qa::Authorities
|
|
|
66
70
|
graph
|
|
67
71
|
end
|
|
68
72
|
|
|
73
|
+
# Filter a graph to remove any statement with a blanknode for the subject
|
|
74
|
+
# @param [RDF::Graph] the graph to be filtered.
|
|
75
|
+
# @returns [RDF::Graph] graph of linked data with blanknodes removed
|
|
76
|
+
def filter_out_blanknodes(graph)
|
|
77
|
+
return graph if graph.subjects.blank?
|
|
78
|
+
graph.each do |st|
|
|
79
|
+
graph.delete(st) if st.subject.anonymous?
|
|
80
|
+
end
|
|
81
|
+
graph
|
|
82
|
+
end
|
|
83
|
+
|
|
69
84
|
def normalize_language(language)
|
|
70
85
|
language = [language.to_sym] if language.is_a? String
|
|
71
86
|
language = [language] if language.is_a? Symbol
|
|
@@ -37,6 +37,7 @@ module Qa::Authorities
|
|
|
37
37
|
|
|
38
38
|
def parse_search_authority_response(graph, language)
|
|
39
39
|
graph = filter_language(graph, language) unless language.nil?
|
|
40
|
+
graph = filter_out_blanknodes(graph)
|
|
40
41
|
results = extract_preds(graph, preds_for_search)
|
|
41
42
|
consolidated_results = consolidate_search_results(results)
|
|
42
43
|
json_results = convert_search_to_json(consolidated_results)
|
|
@@ -61,7 +62,7 @@ module Qa::Authorities
|
|
|
61
62
|
preds
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
def consolidate_search_results(results)
|
|
65
|
+
def consolidate_search_results(results) # rubocop:disable Metrics/MethodLength
|
|
65
66
|
consolidated_results = {}
|
|
66
67
|
return consolidated_results if results.nil? || !results.count.positive?
|
|
67
68
|
results.each do |statement|
|
|
@@ -105,11 +106,14 @@ module Qa::Authorities
|
|
|
105
106
|
lbl
|
|
106
107
|
end
|
|
107
108
|
|
|
108
|
-
def sort_search_results(json_results)
|
|
109
|
+
def sort_search_results(json_results) # rubocop:disable Metrics/MethodLength
|
|
109
110
|
return json_results unless supports_sort?
|
|
110
111
|
json_results.sort! do |a, b|
|
|
111
112
|
cmp = sort_when_missing_sort_predicate(a, b)
|
|
112
|
-
next unless cmp.nil?
|
|
113
|
+
next cmp unless cmp.nil?
|
|
114
|
+
|
|
115
|
+
cmp = numeric_sort(a, b)
|
|
116
|
+
next cmp unless cmp.nil?
|
|
113
117
|
|
|
114
118
|
as = a[:sort].collect(&:downcase)
|
|
115
119
|
bs = b[:sort].collect(&:downcase)
|
|
@@ -138,6 +142,18 @@ module Qa::Authorities
|
|
|
138
142
|
return 1 if bs.size <= current_list_size # consider shorter b list of values lower then longer a list
|
|
139
143
|
nil
|
|
140
144
|
end
|
|
145
|
+
|
|
146
|
+
def numeric_sort(a, b)
|
|
147
|
+
return nil if a[:sort].size > 1
|
|
148
|
+
return nil if b[:sort].size > 1
|
|
149
|
+
return nil unless s_is_i? a[:sort][0]
|
|
150
|
+
return nil unless s_is_i? b[:sort][0]
|
|
151
|
+
Integer(a[:sort][0]) <=> Integer(b[:sort][0])
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def s_is_i?(s)
|
|
155
|
+
/\A[-+]?\d+\z/ === s # rubocop:disable Style/CaseEquality
|
|
156
|
+
end
|
|
141
157
|
end
|
|
142
158
|
end
|
|
143
159
|
end
|
|
@@ -26,7 +26,7 @@ module Qa::Authorities
|
|
|
26
26
|
def build_query_url(q)
|
|
27
27
|
escaped_query = URI.escape(q)
|
|
28
28
|
authority_fragment = Loc.get_url_for_authority(subauthority) + URI.escape(subauthority)
|
|
29
|
-
"
|
|
29
|
+
"https://id.loc.gov/search/?q=#{escaped_query}&q=#{authority_fragment}&format=json"
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def find(id)
|
|
@@ -34,7 +34,7 @@ module Qa::Authorities
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def find_url(id)
|
|
37
|
-
"
|
|
37
|
+
"https://id.loc.gov/authorities/#{@subauthority}/#{id}.json"
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
private
|
|
@@ -18,7 +18,7 @@ module Qa::Authorities::LocSubauthority
|
|
|
18
18
|
]
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def vocabularies
|
|
21
|
+
def vocabularies # rubocop:disable Metrics/MethodLength
|
|
22
22
|
[
|
|
23
23
|
"graphicMaterials",
|
|
24
24
|
"organizations",
|
|
@@ -40,7 +40,7 @@ module Qa::Authorities::LocSubauthority
|
|
|
40
40
|
["edtf"]
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def preservation
|
|
43
|
+
def preservation # rubocop:disable Metrics/MethodLength
|
|
44
44
|
[
|
|
45
45
|
"contentLocationType",
|
|
46
46
|
"copyrightStatus",
|
data/lib/qa/authorities/local.rb
CHANGED
|
@@ -20,15 +20,13 @@ module Qa::Authorities
|
|
|
20
20
|
if config[:local_path].starts_with?(File::Separator)
|
|
21
21
|
config[:local_path]
|
|
22
22
|
else
|
|
23
|
-
|
|
23
|
+
Rails.root.join(config[:local_path]).to_s # TODO: Rails.root.join returns class Pathname, which may be ok. Added to_s because of failing regression test.
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Local sub-authorities are any YAML files in the subauthorities_path
|
|
28
28
|
def names
|
|
29
|
-
unless Dir.exist? subauthorities_path
|
|
30
|
-
raise Qa::ConfigDirectoryNotFound, "There's no directory at #{subauthorities_path}. You must create it in order to use local authorities"
|
|
31
|
-
end
|
|
29
|
+
raise Qa::ConfigDirectoryNotFound, "There's no directory at #{subauthorities_path}. You must create it in order to use local authorities" unless Dir.exist? subauthorities_path
|
|
32
30
|
Dir.entries(subauthorities_path).map { |f| File.basename(f, ".yml") if f =~ /yml$/ }.compact
|
|
33
31
|
end
|
|
34
32
|
|
|
@@ -25,7 +25,7 @@ module Qa::Authorities
|
|
|
25
25
|
private
|
|
26
26
|
|
|
27
27
|
def terms
|
|
28
|
-
subauthority_hash = YAML.load(File.read(subauthority_filename))
|
|
28
|
+
subauthority_hash = YAML.load(File.read(subauthority_filename)) # rubocop:disable Security/YAMLLoad # TODO: Explore how to change this to safe_load. Many tests fail when making this change.
|
|
29
29
|
terms = subauthority_hash.with_indifferent_access.fetch(:terms, [])
|
|
30
30
|
normalize_terms(terms)
|
|
31
31
|
end
|
|
@@ -5,8 +5,7 @@ module Qa
|
|
|
5
5
|
self.table_index = "index_qa_local_authority_entries_on_lower_label_and_authority"
|
|
6
6
|
|
|
7
7
|
def self.check_for_index
|
|
8
|
-
|
|
9
|
-
if table_or_view_exists? && conn.index_name_exists?(table_name.to_sym, table_index, :default).blank?
|
|
8
|
+
if table_or_view_exists? && index_name_exists? # rubocop:disable Style/GuardClause
|
|
10
9
|
Rails.logger.error "You've installed mysql local authority tables, but you haven't indexed the lower label. "
|
|
11
10
|
"Rails doesn't support functional indexes in migrations, so we tried to execute it for you but something went wrong...\n" \
|
|
12
11
|
"Make sure your table has a lower_label column, which is virtually created, and that the column is indexed." \
|
|
@@ -19,6 +18,16 @@ module Qa
|
|
|
19
18
|
return [] if q.blank?
|
|
20
19
|
output_set(base_relation.where('lower_label like ?', "#{q.downcase}%").limit(25))
|
|
21
20
|
end
|
|
21
|
+
|
|
22
|
+
def self.index_name_exists?
|
|
23
|
+
conn = ActiveRecord::Base.connection
|
|
24
|
+
if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
|
|
25
|
+
conn.index_name_exists?(table_name, table_index).blank?
|
|
26
|
+
else
|
|
27
|
+
conn.index_name_exists?(table_name, table_index, :default).blank?
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
private_class_method :index_name_exists?
|
|
22
31
|
end
|
|
23
32
|
end
|
|
24
33
|
end
|