qa 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +284 -2
- data/app/controllers/qa/linked_data_terms_controller.rb +127 -0
- data/config/authorities/linked_data/agrovoc.json +61 -0
- data/config/authorities/linked_data/loc.json +46 -0
- data/config/authorities/linked_data/oclc_fast.json +78 -0
- data/config/initializers/linked_data_authorities.rb +17 -0
- data/config/routes.rb +3 -0
- data/lib/qa.rb +15 -0
- data/lib/qa/authorities.rb +2 -0
- data/lib/qa/authorities/base.rb +1 -1
- data/lib/qa/authorities/crossref.rb +16 -0
- data/lib/qa/authorities/crossref/generic_authority.rb +63 -0
- data/lib/qa/authorities/geonames.rb +2 -1
- data/lib/qa/authorities/linked_data.rb +10 -0
- data/lib/qa/authorities/linked_data/config.rb +80 -0
- data/lib/qa/authorities/linked_data/config/search_config.rb +170 -0
- data/lib/qa/authorities/linked_data/config/term_config.rb +186 -0
- data/lib/qa/authorities/linked_data/find_term.rb +148 -0
- data/lib/qa/authorities/linked_data/generic_authority.rb +49 -0
- data/lib/qa/authorities/linked_data/rdf_helper.rb +102 -0
- data/lib/qa/authorities/linked_data/search_query.rb +143 -0
- data/lib/qa/version.rb +1 -1
- data/spec/controllers/linked_data_terms_controller_spec.rb +202 -0
- data/spec/fixtures/authorities/linked_data/lod_full_config.json +111 -0
- data/spec/fixtures/authorities/linked_data/lod_lang_defaults.json +54 -0
- data/spec/fixtures/authorities/linked_data/lod_lang_multi_defaults.json +54 -0
- data/spec/fixtures/authorities/linked_data/lod_lang_no_defaults.json +52 -0
- data/spec/fixtures/authorities/linked_data/lod_lang_param.json +66 -0
- data/spec/fixtures/authorities/linked_data/lod_min_config.json +49 -0
- data/spec/fixtures/authorities/linked_data/lod_search_only_config.json +55 -0
- data/spec/fixtures/authorities/linked_data/lod_sort.json +27 -0
- data/spec/fixtures/authorities/linked_data/lod_term_only_config.json +59 -0
- data/spec/fixtures/funders-find-response.json +1 -0
- data/spec/fixtures/funders-noquery.json +1 -0
- data/spec/fixtures/funders-noresults.json +1 -0
- data/spec/fixtures/funders-result.json +1 -0
- data/spec/fixtures/journals-find-response-two-issn.json +1 -0
- data/spec/fixtures/journals-find-response.json +1 -0
- data/spec/fixtures/journals-noquery.json +1 -0
- data/spec/fixtures/journals-noresults.json +1 -0
- data/spec/fixtures/journals-result.json +705 -0
- data/spec/fixtures/lod_agrovoc_query_many_results.json +1 -0
- data/spec/fixtures/lod_agrovoc_query_no_results.json +1 -0
- data/spec/fixtures/lod_agrovoc_term_found.rdf.xml +217 -0
- data/spec/fixtures/lod_lang_search_en.rdf.xml +42 -0
- data/spec/fixtures/lod_lang_search_enfr.rdf.xml +48 -0
- data/spec/fixtures/lod_lang_search_enfrde.rdf.xml +54 -0
- data/spec/fixtures/lod_lang_search_fr.rdf.xml +42 -0
- data/spec/fixtures/lod_lang_term_en.rdf.xml +65 -0
- data/spec/fixtures/lod_lang_term_enfr.rdf.xml +71 -0
- data/spec/fixtures/lod_lang_term_enfr_noalt.rdf.xml +69 -0
- data/spec/fixtures/lod_lang_term_enfrde.rdf.xml +79 -0
- data/spec/fixtures/lod_lang_term_fr.rdf.xml +65 -0
- data/spec/fixtures/lod_loc_term_found.rdf.xml +262 -0
- data/spec/fixtures/lod_oclc_all_query_3_results.rdf.xml +142 -0
- data/spec/fixtures/lod_oclc_personalName_query_3_results.rdf.xml +128 -0
- data/spec/fixtures/lod_oclc_query_no_results.rdf.xml +13 -0
- data/spec/fixtures/lod_oclc_term_found.rdf.xml +51 -0
- data/spec/lib/authorities/crossref_spec.rb +180 -0
- data/spec/lib/authorities/geonames_spec.rb +2 -2
- data/spec/lib/authorities/linked_data/config_spec.rb +143 -0
- data/spec/lib/authorities/linked_data/find_term_spec.rb +5 -0
- data/spec/lib/authorities/linked_data/generic_authority_spec.rb +580 -0
- data/spec/lib/authorities/linked_data/search_config_spec.rb +385 -0
- data/spec/lib/authorities/linked_data/search_query_spec.rb +79 -0
- data/spec/lib/authorities/linked_data/term_config_spec.rb +419 -0
- data/spec/routing/linked_data_route_spec.rb +35 -0
- data/spec/spec_helper.rb +2 -0
- metadata +184 -39
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"term": {
|
3
|
+
"url": {
|
4
|
+
"@context": "http://www.w3.org/ns/hydra/context.jsonld",
|
5
|
+
"@type": "IriTemplate",
|
6
|
+
"template": "http://id.loc.gov/authorities/{?subauth}/{?term_id}",
|
7
|
+
"variableRepresentation": "BasicRepresentation",
|
8
|
+
"mapping": [
|
9
|
+
{
|
10
|
+
"@type": "IriTemplateMapping",
|
11
|
+
"variable": "term_id",
|
12
|
+
"property": "hydra:freetextQuery",
|
13
|
+
"required": true
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"@type": "IriTemplateMapping",
|
17
|
+
"variable": "subauth",
|
18
|
+
"property": "hydra:freetextQuery",
|
19
|
+
"required": false,
|
20
|
+
"default": "names"
|
21
|
+
}
|
22
|
+
]
|
23
|
+
},
|
24
|
+
"qa_replacement_patterns": {
|
25
|
+
"term_id": "term_id",
|
26
|
+
"subauth": "subauth"
|
27
|
+
},
|
28
|
+
"term_id": "ID",
|
29
|
+
"language": ["en"],
|
30
|
+
"results": {
|
31
|
+
"id_predicate": "http://id.loc.gov/vocabulary/identifiers/lccn",
|
32
|
+
"label_predicate": "http://www.w3.org/2004/02/skos/core#prefLabel",
|
33
|
+
"altlabel_predicate": "http://www.w3.org/2004/02/skos/core#altLabel",
|
34
|
+
"sameas_predicate": "http://www.w3.org/2004/02/skos/core#exactMatch"
|
35
|
+
},
|
36
|
+
"subauthorities": {
|
37
|
+
"subjects": "subjects",
|
38
|
+
"names": "names",
|
39
|
+
"classification": "classification",
|
40
|
+
"child_subject": "childrensSubjects",
|
41
|
+
"genre": "genreForms",
|
42
|
+
"demographic": "demographicTerms"
|
43
|
+
}
|
44
|
+
},
|
45
|
+
"search": {}
|
46
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
{
|
2
|
+
"term": {
|
3
|
+
"url": {
|
4
|
+
"@context": "http://www.w3.org/ns/hydra/context.jsonld",
|
5
|
+
"@type": "IriTemplate",
|
6
|
+
"template": "http://id.worldcat.org/fast/{?term_id}",
|
7
|
+
"variableRepresentation": "BasicRepresentation",
|
8
|
+
"mapping": [
|
9
|
+
{
|
10
|
+
"@type": "IriTemplateMapping",
|
11
|
+
"variable": "term_id",
|
12
|
+
"property": "hydra:freetextQuery",
|
13
|
+
"required": true
|
14
|
+
}
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"qa_replacement_patterns": {
|
18
|
+
"term_id": "term_id"
|
19
|
+
},
|
20
|
+
"term_id": "ID",
|
21
|
+
"results": {
|
22
|
+
"id_predicate": "http://purl.org/dc/terms/identifier",
|
23
|
+
"label_predicate": "http://www.w3.org/2004/02/skos/core#prefLabel",
|
24
|
+
"altlabel_predicate": "http://www.w3.org/2004/02/skos/core#altLabel",
|
25
|
+
"sameas_predicate": "http://schema.org/sameAs"
|
26
|
+
}
|
27
|
+
},
|
28
|
+
"search": {
|
29
|
+
"url": {
|
30
|
+
"@context": "http://www.w3.org/ns/hydra/context.jsonld",
|
31
|
+
"@type": "IriTemplate",
|
32
|
+
"template": "http://experimental.worldcat.org/fast/search?query={?subauth}+all+%22{?query}%22&sortKeys=usage&maximumRecords={?maximumRecords}",
|
33
|
+
"variableRepresentation": "BasicRepresentation",
|
34
|
+
"mapping": [
|
35
|
+
{
|
36
|
+
"@type": "IriTemplateMapping",
|
37
|
+
"variable": "query",
|
38
|
+
"property": "hydra:freetextQuery",
|
39
|
+
"required": true
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"@type": "IriTemplateMapping",
|
43
|
+
"variable": "subauth",
|
44
|
+
"property": "hydra:freetextQuery",
|
45
|
+
"required": false,
|
46
|
+
"default": "cql.any"
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"@type": "IriTemplateMapping",
|
50
|
+
"variable": "maximumRecords",
|
51
|
+
"property": "hydra:freetextQuery",
|
52
|
+
"required": false,
|
53
|
+
"default": "20"
|
54
|
+
}
|
55
|
+
]
|
56
|
+
},
|
57
|
+
"qa_replacement_patterns": {
|
58
|
+
"query": "query",
|
59
|
+
"subauth": "subauth"
|
60
|
+
},
|
61
|
+
"results": {
|
62
|
+
"id_predicate": "http://purl.org/dc/terms/identifier",
|
63
|
+
"label_predicate": "http://www.w3.org/2004/02/skos/core#prefLabel",
|
64
|
+
"sort_predicate": "http://www.w3.org/2004/02/skos/core#prefLabel"
|
65
|
+
},
|
66
|
+
"subauthorities": {
|
67
|
+
"topic": "oclc.topic",
|
68
|
+
"geographic": "oclc.geographic",
|
69
|
+
"event_name": "oclc.eventName",
|
70
|
+
"personal_name": "oclc.personalName",
|
71
|
+
"corporate_name": "oclc.corporateName",
|
72
|
+
"uniform_title": "oclc.uniformTitle",
|
73
|
+
"period": "oclc.period",
|
74
|
+
"form": "oclc.form",
|
75
|
+
"alt_lc": "oclc.altlc"
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
auth_cfg = {}
|
2
|
+
# load QA configured linked data authorities
|
3
|
+
Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
4
|
+
auth = File.basename(fn, '.json').upcase.to_sym
|
5
|
+
json = File.read(File.expand_path(fn, __FILE__))
|
6
|
+
cfg = JSON.parse(json).deep_symbolize_keys
|
7
|
+
auth_cfg[auth] = cfg
|
8
|
+
end
|
9
|
+
|
10
|
+
# load app configured linked data authorities and overrides
|
11
|
+
Dir[File.join(Rails.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
12
|
+
auth = File.basename(fn, '.json').upcase.to_sym
|
13
|
+
json = File.read(File.expand_path(fn, __FILE__))
|
14
|
+
cfg = JSON.parse(json).deep_symbolize_keys
|
15
|
+
auth_cfg[auth] = cfg
|
16
|
+
end
|
17
|
+
LINKED_DATA_AUTHORITIES_CONFIG = auth_cfg.freeze
|
data/config/routes.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
Qa::Engine.routes.draw do
|
2
|
+
get "/search/linked_data/:vocab(/:subauthority)", controller: :linked_data_terms, action: :search
|
3
|
+
get "/show/linked_data/:vocab/:id", controller: :linked_data_terms, action: :show
|
4
|
+
get "/show/linked_data/:vocab/:subauthority/:id", controller: :linked_data_terms, action: :show
|
2
5
|
get "/terms/:vocab(/:subauthority)", controller: :terms, action: :index
|
3
6
|
get "/search/:vocab(/:subauthority)", controller: :terms, action: :search
|
4
7
|
get "/show/:vocab/:id", controller: :terms, action: :show
|
data/lib/qa.rb
CHANGED
@@ -16,4 +16,19 @@ module Qa
|
|
16
16
|
|
17
17
|
# Raised when a subauthority is not valid
|
18
18
|
class InvalidSubAuthority < ArgumentError; end
|
19
|
+
|
20
|
+
# Raised when a request is made to a non-configured linked data authority
|
21
|
+
class InvalidLinkedDataAuthority < ArgumentError; end
|
22
|
+
|
23
|
+
# Raised when a response is in an unsupported format
|
24
|
+
class UnsupportedFormat < ArgumentError; end
|
25
|
+
|
26
|
+
# Raised when a configuration parameter is incorrect or is required and missing
|
27
|
+
class InvalidConfiguration < ArgumentError; end
|
28
|
+
|
29
|
+
# Raised when a linked data request to a server returns a 500 error
|
30
|
+
class ServiceUnavailable < ArgumentError; end
|
31
|
+
|
32
|
+
# Raised when the server returns 404 for a find term request
|
33
|
+
class TermNotFound < ArgumentError; end
|
19
34
|
end
|
data/lib/qa/authorities.rb
CHANGED
data/lib/qa/authorities/base.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'uri'
|
2
|
+
module Qa::Authorities
|
3
|
+
module Crossref
|
4
|
+
require 'qa/authorities/crossref/generic_authority'
|
5
|
+
extend AuthorityWithSubAuthority
|
6
|
+
|
7
|
+
def self.subauthority_for(subauthority)
|
8
|
+
validate_subauthority!(subauthority)
|
9
|
+
GenericAuthority.new(subauthority)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.subauthorities
|
13
|
+
['funders', 'journals']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Qa::Authorities
|
2
|
+
class Crossref::GenericAuthority < Base
|
3
|
+
include WebServiceBase
|
4
|
+
class_attribute :label, :identifier
|
5
|
+
attr_reader :subauthority
|
6
|
+
|
7
|
+
def initialize(subauthority)
|
8
|
+
@subauthority = subauthority
|
9
|
+
end
|
10
|
+
|
11
|
+
# Create a label from the crossref result hash
|
12
|
+
#
|
13
|
+
# @param item [Hash] the crossref result
|
14
|
+
# @return [String] a label combining the name, alt-names and location
|
15
|
+
self.label = lambda do |item|
|
16
|
+
[item['name'],
|
17
|
+
item['alt-names'].blank? ? nil : "(#{item['alt-names'].join(', ')})",
|
18
|
+
item['location']].compact.join(', ')
|
19
|
+
end
|
20
|
+
|
21
|
+
def search(q)
|
22
|
+
parse_authority_response(json(build_query_url(q)))
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_query_url(q)
|
26
|
+
query = URI.escape(untaint(q))
|
27
|
+
"http://api.crossref.org/#{subauthority}?query=#{query}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def untaint(q)
|
31
|
+
q.gsub(/[^\w\s-]/, '')
|
32
|
+
end
|
33
|
+
|
34
|
+
def find(id)
|
35
|
+
json(find_url(id))
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_url(id)
|
39
|
+
"http://api.crossref.org/#{subauthority}/#{id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Reformats the data received from the service
|
45
|
+
def parse_authority_response(response)
|
46
|
+
response['message']['items'].map do |result|
|
47
|
+
case subauthority
|
48
|
+
when 'funders'
|
49
|
+
{ id: result['id'],
|
50
|
+
uri: result['uri'],
|
51
|
+
label: label.call(result),
|
52
|
+
value: result['name'] }
|
53
|
+
when 'journals'
|
54
|
+
{ id: result['ISSN'].first,
|
55
|
+
label: result['title'],
|
56
|
+
publisher: result['publisher'],
|
57
|
+
issn: result['ISSN'] }
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -38,7 +38,8 @@ module Qa::Authorities
|
|
38
38
|
# Reformats the data received from the service
|
39
39
|
def parse_authority_response(response)
|
40
40
|
response['geonames'].map do |result|
|
41
|
-
|
41
|
+
# Note: the trailing slash is meaningful.
|
42
|
+
{ 'id' => "http://sws.geonames.org/#{result['geonameId']}/",
|
42
43
|
'label' => label.call(result) }
|
43
44
|
end
|
44
45
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'qa/authorities/linked_data/config/term_config'.freeze
|
2
|
+
require 'qa/authorities/linked_data/config/search_config'.freeze
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# Provide attr_reader methods for linked data authority configurations. Some default configurations are provided for several
|
6
|
+
# linked data authorities and can be found at /config/authorities/linked_data. You can add configurations for new authorities by
|
7
|
+
# adding the configuration at YOUR_APP/config/authorities/linked_data. You can modify a QA provided configuration by copying
|
8
|
+
# it to YOUR_APP/config/authorities/linked_data and making the modifications there. See README for more information on the
|
9
|
+
# structure of the configuration.
|
10
|
+
#
|
11
|
+
# This configuration processed by this class is used by Qa::Authorities::LinkedData::GenericAuthority to drive url construction
|
12
|
+
# and results processing for a specific linked data authority.
|
13
|
+
#
|
14
|
+
# @see Qa::Authorities::LinkedData::GenericAuthority#initialize
|
15
|
+
# @see Qa::Authorities::LinkedData::TermConfig
|
16
|
+
# @see Qa::Authorities::LinkedData::SearchConfig
|
17
|
+
module Qa::Authorities
|
18
|
+
module LinkedData
|
19
|
+
class Config
|
20
|
+
attr_reader :authority_name
|
21
|
+
attr_reader :authority_config
|
22
|
+
|
23
|
+
# Initialize to hold the configuration for the specifed authority. Configurations are defined in config/authorities/linked_data. See README for more information.
|
24
|
+
# @param [String] the name of the configuration file for the authority
|
25
|
+
# @return [Qa::Authorities::LinkedData::Config] instance of this class
|
26
|
+
def initialize(auth_name)
|
27
|
+
@authority_name = auth_name
|
28
|
+
auth_config
|
29
|
+
end
|
30
|
+
|
31
|
+
def search
|
32
|
+
@search ||= Qa::Authorities::LinkedData::SearchConfig.new(auth_config.fetch(:search))
|
33
|
+
end
|
34
|
+
|
35
|
+
def term
|
36
|
+
@term ||= Qa::Authorities::LinkedData::TermConfig.new(auth_config.fetch(:term))
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the full configuration for an authority
|
40
|
+
# @return [String] the authority configuration
|
41
|
+
def auth_config
|
42
|
+
@authority_config ||= LINKED_DATA_AUTHORITIES_CONFIG[@authority_name]
|
43
|
+
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data authority '#{@authority_name}'" if @authority_config.nil?
|
44
|
+
@authority_config
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.config_value(config, key)
|
48
|
+
return nil if config.nil? || !(config.key? key)
|
49
|
+
config[key]
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.predicate_uri(config, key)
|
53
|
+
pred = config_value(config, key)
|
54
|
+
pred_uri = nil
|
55
|
+
pred_uri = RDF::URI(pred) unless pred.nil? || pred.length <= 0
|
56
|
+
pred_uri
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.replace_pattern(url, pattern, value)
|
60
|
+
url.gsub("{?#{pattern}}", value)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.process_subauthority(url, subauth_pattern, subauthorities, subauth_key)
|
64
|
+
pattern = subauth_pattern[:pattern]
|
65
|
+
value = subauthorities[subauth_key] || subauth_pattern[:default]
|
66
|
+
replace_pattern(url, pattern, value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.apply_replacements(url, config, replacements = {})
|
70
|
+
return url unless config.size.positive?
|
71
|
+
config.each do |param_key, rep_pattern|
|
72
|
+
s_param_key = param_key.to_s
|
73
|
+
value = replacements[param_key] || replacements[s_param_key] || rep_pattern[:default]
|
74
|
+
url = replace_pattern(url, param_key, value)
|
75
|
+
end
|
76
|
+
url
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# Provide attr_reader methods specific to search configuration for linked data authority configurations. This is separated
|
2
|
+
# out for readability and file length.
|
3
|
+
# @see Qa::Authorities::LinkedData::Config
|
4
|
+
# @see Qa::Authorities::LinkedData::TermConfig
|
5
|
+
module Qa::Authorities
|
6
|
+
module LinkedData
|
7
|
+
class SearchConfig
|
8
|
+
# @param [Hash] config the search portion of the config
|
9
|
+
def initialize(config)
|
10
|
+
@search_config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :search_config
|
14
|
+
private :search_config
|
15
|
+
|
16
|
+
# Does this authority configuration have search defined?
|
17
|
+
# @return [Boolean] true if search is configured; otherwise, false
|
18
|
+
def supports_search?
|
19
|
+
search_config.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return search url encoding defined in the configuration for this authority
|
23
|
+
# if it was provided
|
24
|
+
# @return [Hash,NilClass] the configured search url
|
25
|
+
def url
|
26
|
+
search_config[:url]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return search url template defined in the configuration for this authority.
|
30
|
+
# @return [String] the configured search url template
|
31
|
+
def url_template
|
32
|
+
url.fetch(:template)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Return search url parameter mapping defined in the configuration for this authority.
|
36
|
+
# @return [Hash] the configured search url parameter mappings with variable name as key
|
37
|
+
def url_mappings
|
38
|
+
return @url_mappings unless @url_mappings.nil?
|
39
|
+
mappings = Config.config_value(url, :mapping)
|
40
|
+
return {} if mappings.nil?
|
41
|
+
Hash[*mappings.collect { |m| [m[:variable].to_sym, m] }.flatten]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return the preferred language for literal value selection for search query.
|
45
|
+
# Only applies if the authority provides language encoded literals.
|
46
|
+
# @return [String] the configured language for search query
|
47
|
+
def language
|
48
|
+
return @language unless @language.nil?
|
49
|
+
lang = search_config[:language]
|
50
|
+
return nil if lang.nil?
|
51
|
+
lang = [lang] if lang.is_a? String
|
52
|
+
@language = lang.collect(&:to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Return results predicates if specified
|
56
|
+
# @return [Hash,NilClass] all the configured predicates to pull out of the results
|
57
|
+
def results
|
58
|
+
search_config[:results]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return results id_predicate
|
62
|
+
# @return [String] the configured predicate to use to extract the id from the results
|
63
|
+
def results_id_predicate
|
64
|
+
Config.predicate_uri(results, :id_predicate)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return results label_predicate
|
68
|
+
# @return [String] the configured predicate to use to extract label values from the results
|
69
|
+
def results_label_predicate
|
70
|
+
Config.predicate_uri(results, :label_predicate)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return results altlabel_predicate
|
74
|
+
# @return [String] the configured predicate to use to extract altlabel values from the results
|
75
|
+
def results_altlabel_predicate
|
76
|
+
Config.predicate_uri(results, :altlabel_predicate)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Does this authority configuration support sorting of search results?
|
80
|
+
# @return [True|False] true if sorting of search results is supported; otherwise, false
|
81
|
+
def supports_sort?
|
82
|
+
return true unless results_sort_predicate.nil? || !results_sort_predicate.size.positive?
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return results sort_predicate
|
87
|
+
# @return [String] the configured predicate to use for sorting results from the query search
|
88
|
+
def results_sort_predicate
|
89
|
+
Config.predicate_uri(results, :sort_predicate)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return parameters that are required for QA api
|
93
|
+
# @return [Hash] the configured search url parameter mappings
|
94
|
+
def qa_replacement_patterns
|
95
|
+
search_config.fetch(:qa_replacement_patterns)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Are there replacement parameters configured for search query?
|
99
|
+
# @return [True|False] true if there are replacement parameters configured for search query; otherwise, false
|
100
|
+
def replacements?
|
101
|
+
replacement_count.positive?
|
102
|
+
end
|
103
|
+
|
104
|
+
# Return the number of possible replacement values to make in the search URL
|
105
|
+
# @return [Integer] the configured number of possible replacements in the search url
|
106
|
+
def replacement_count
|
107
|
+
replacements.size
|
108
|
+
end
|
109
|
+
|
110
|
+
# Return the replacement configurations
|
111
|
+
# @return [Hash] the configurations for search url replacements
|
112
|
+
def replacements
|
113
|
+
return @replacements unless @replacements.nil?
|
114
|
+
@replacements = {}
|
115
|
+
@replacements = url_mappings.select { |k, _v| !qa_replacement_patterns.include?(k) } unless search_config.nil? || url_mappings.nil?
|
116
|
+
@replacements
|
117
|
+
end
|
118
|
+
|
119
|
+
# Are there subauthorities configured for search query?
|
120
|
+
# @return [True|False] true if there are subauthorities configured for search query; otherwise, false
|
121
|
+
def subauthorities?
|
122
|
+
subauthority_count.positive?
|
123
|
+
end
|
124
|
+
|
125
|
+
# Is a specific subauthority configured for search query?
|
126
|
+
# @return [True|False] true if the specified subauthority is configured for search query; otherwise, false
|
127
|
+
def subauthority?(subauth_name)
|
128
|
+
subauth_name = subauth_name.to_sym if subauth_name.is_a? String
|
129
|
+
subauthorities.key? subauth_name
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return the number of subauthorities defined for search query
|
133
|
+
# @return [Integer] the number of subauthorities defined for search query
|
134
|
+
def subauthority_count
|
135
|
+
subauthorities.size
|
136
|
+
end
|
137
|
+
|
138
|
+
# Return the list of subauthorities for search query
|
139
|
+
# @return [Hash] the configurations for search url replacements
|
140
|
+
def subauthorities
|
141
|
+
@subauthorities ||= {} if search_config.nil? || !(search_config.key? :subauthorities)
|
142
|
+
@subauthorities ||= search_config.fetch(:subauthorities)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Return the replacement configurations
|
146
|
+
# @return [Hash] the configurations for search url replacements
|
147
|
+
def subauthority_replacement_pattern
|
148
|
+
return {} unless subauthorities?
|
149
|
+
@subauthority_replacement_pattern ||= {} if search_config.nil? || !subauthorities?
|
150
|
+
pattern = qa_replacement_patterns[:subauth]
|
151
|
+
default = url_mappings[pattern.to_sym][:default]
|
152
|
+
@subauthority_replacement_pattern ||= { pattern: pattern, default: default }
|
153
|
+
end
|
154
|
+
|
155
|
+
# Build a linked data authority search url
|
156
|
+
# @param [String] the query
|
157
|
+
# @param [String] (optional) subauthority key
|
158
|
+
# @param [Hash] (optional) replacement values with { pattern_name (defined in YAML config) => value }
|
159
|
+
# @return [String] the search encoded url
|
160
|
+
def url_with_replacements(query, sub_auth = nil, search_replacements = {})
|
161
|
+
return nil unless supports_search?
|
162
|
+
sub_auth = sub_auth.to_sym if sub_auth.is_a? String
|
163
|
+
url = Config.replace_pattern(url_template, qa_replacement_patterns[:query], query)
|
164
|
+
url = Config.process_subauthority(url, subauthority_replacement_pattern, subauthorities, sub_auth) if subauthorities?
|
165
|
+
url = Config.apply_replacements(url, replacements, search_replacements) if replacements?
|
166
|
+
url
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|