qa 1.0.0 → 1.1.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/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
|