qa 4.0.0 → 4.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/controllers/qa/linked_data_terms_controller.rb +30 -9
  4. data/app/controllers/qa/terms_controller.rb +3 -2
  5. data/app/models/qa/linked_data/config/context_property_map.rb +6 -25
  6. data/app/services/qa/iri_template_service.rb +32 -24
  7. data/app/services/qa/linked_data/authority_service.rb +8 -0
  8. data/app/services/qa/linked_data/authority_url_service.rb +27 -8
  9. data/app/services/qa/linked_data/deep_sort_service.rb +3 -2
  10. data/app/services/qa/linked_data/graph_service.rb +13 -0
  11. data/app/services/qa/linked_data/language_service.rb +12 -0
  12. data/app/services/qa/linked_data/language_sort_service.rb +7 -2
  13. data/app/services/qa/linked_data/ldpath_service.rb +40 -0
  14. data/app/services/qa/linked_data/mapper/graph_ldpath_mapper_service.rb +49 -0
  15. data/app/services/qa/linked_data/mapper/graph_mapper_service.rb +3 -11
  16. data/app/services/qa/linked_data/mapper/graph_predicate_mapper_service.rb +40 -0
  17. data/app/services/qa/linked_data/mapper/search_results_mapper_service.rb +58 -11
  18. data/app/services/qa/linked_data/mapper/term_results_mapper_service.rb +80 -0
  19. data/config/authorities/linked_data/loc.json +13 -7
  20. data/config/authorities/linked_data/oclc_fast.json +13 -8
  21. data/lib/generators/qa/discogs/USAGE +10 -0
  22. data/lib/generators/qa/discogs/discogs_generator.rb +12 -0
  23. data/lib/generators/qa/discogs/templates/config/discogs-formats.yml +346 -0
  24. data/lib/generators/qa/discogs/templates/config/discogs-genres.yml +627 -0
  25. data/lib/generators/qa/install/templates/config/initializers/qa.rb +4 -0
  26. data/lib/qa.rb +6 -0
  27. data/lib/qa/authorities.rb +2 -0
  28. data/lib/qa/authorities/discogs.rb +28 -0
  29. data/lib/qa/authorities/discogs/discogs_instance_builder.rb +145 -0
  30. data/lib/qa/authorities/discogs/discogs_translation.rb +126 -0
  31. data/lib/qa/authorities/discogs/discogs_utils.rb +89 -0
  32. data/lib/qa/authorities/discogs/discogs_works_builder.rb +153 -0
  33. data/lib/qa/authorities/discogs/generic_authority.rb +151 -0
  34. data/lib/qa/authorities/discogs_subauthority.rb +9 -0
  35. data/lib/qa/authorities/linked_data/config.rb +7 -3
  36. data/lib/qa/authorities/linked_data/config/search_config.rb +99 -11
  37. data/lib/qa/authorities/linked_data/config/term_config.rb +112 -8
  38. data/lib/qa/authorities/linked_data/find_term.rb +154 -84
  39. data/lib/qa/authorities/linked_data/search_query.rb +76 -13
  40. data/lib/qa/configuration.rb +8 -0
  41. data/lib/qa/version.rb +1 -1
  42. data/spec/controllers/linked_data_terms_controller_spec.rb +151 -30
  43. data/spec/controllers/terms_controller_spec.rb +4 -0
  44. data/spec/features/linked_data/language_spec.rb +298 -0
  45. data/spec/fixtures/authorities/linked_data/lod_full_config.json +21 -5
  46. data/spec/fixtures/authorities/linked_data/lod_lang_defaults.json +4 -4
  47. data/spec/fixtures/authorities/linked_data/lod_lang_multi_defaults.json +4 -4
  48. data/spec/fixtures/authorities/linked_data/lod_lang_no_defaults.json +4 -5
  49. data/spec/fixtures/authorities/linked_data/lod_lang_param.json +4 -4
  50. data/spec/fixtures/authorities/linked_data/lod_term_uri_param_config.json +1 -1
  51. data/spec/fixtures/discogs-find-response-json.json +1 -0
  52. data/spec/fixtures/discogs-find-response-jsonld-master.json +1 -0
  53. data/spec/fixtures/discogs-find-response-jsonld-release.json +1 -0
  54. data/spec/fixtures/discogs-id-matches-master.json +1 -0
  55. data/spec/fixtures/discogs-id-matches-release.json +1 -0
  56. data/spec/fixtures/discogs-id-not-found-master.json +1 -0
  57. data/spec/fixtures/discogs-id-not-found-release.json +1 -0
  58. data/spec/fixtures/discogs-search-response-no-auth.json +1 -0
  59. data/spec/fixtures/discogs-search-response-no-subauth.json +1 -0
  60. data/spec/fixtures/discogs-search-response-subauth.json +1 -0
  61. data/spec/fixtures/lod_lang_search_enesfrde.rdf.xml +60 -0
  62. data/spec/fixtures/lod_lang_search_sv.rdf.xml +42 -0
  63. data/spec/fixtures/lod_loc_term_found.rdf.xml +5 -0
  64. data/spec/lib/authorities/discogs/generic_authority_spec.rb +235 -0
  65. data/spec/lib/authorities/discogs_spec.rb +17 -0
  66. data/spec/lib/authorities/linked_data/config_spec.rb +68 -5
  67. data/spec/lib/authorities/linked_data/find_term_spec.rb +298 -3
  68. data/spec/lib/authorities/linked_data/generic_authority_spec.rb +46 -485
  69. data/spec/lib/authorities/linked_data/search_config_spec.rb +154 -3
  70. data/spec/lib/authorities/linked_data/search_query_spec.rb +240 -3
  71. data/spec/lib/authorities/linked_data/term_config_spec.rb +193 -5
  72. data/spec/lib/configuration_spec.rb +18 -0
  73. data/spec/models/linked_data/config/context_property_map_spec.rb +3 -31
  74. data/spec/services/iri_template_service_spec.rb +54 -12
  75. data/spec/{lib/authorities → services}/linked_data/authority_service_spec.rb +47 -0
  76. data/spec/services/linked_data/language_service_spec.rb +52 -11
  77. data/spec/services/linked_data/ldpath_service_spec.rb +61 -0
  78. data/spec/services/linked_data/mapper/graph_ldpath_mapper_service_spec.rb +118 -0
  79. data/spec/services/linked_data/mapper/graph_predicate_mapper_service_spec.rb +110 -0
  80. data/spec/services/linked_data/mapper/term_results_mapper_service_spec.rb +94 -0
  81. data/spec/spec_helper.rb +1 -1
  82. data/spec/support/matchers/include_hash.rb +5 -0
  83. data/spec/test_app_templates/lib/generators/test_app_generator.rb +4 -0
  84. metadata +73 -5
  85. data/lib/qa/authorities/linked_data/rdf_helper.rb +0 -49
@@ -0,0 +1,151 @@
1
+ require 'rdf'
2
+ module Qa::Authorities
3
+ class Discogs::GenericAuthority < Base
4
+ include WebServiceBase
5
+ include Discogs::DiscogsTranslation
6
+
7
+ class_attribute :discogs_secret, :discogs_key
8
+ attr_accessor :primary_artists
9
+
10
+ # @param [String] subauthority to use
11
+ def initialize(subauthority)
12
+ @subauthority = subauthority
13
+ self.primary_artists = []
14
+ end
15
+
16
+ # @param [String] the query
17
+ # @param [Class] QA::TermsController
18
+ # @return json results
19
+ def search(q, tc)
20
+ # Discogs distinguishes between masters and releases, where a release represents a specific
21
+ # physical or digital object and a master represents a set of similar releases. Use of a
22
+ # subauthority (e.g., /qa/search/discogs/master) will target a specific type. Using the "all"
23
+ # subauthority will search for both types.
24
+ unless discogs_key && discogs_secret
25
+ Rails.logger.error "Questioning Authority tried to call Discogs, but no secret and/or key were set."
26
+ return []
27
+ end
28
+ parse_authority_response(json(build_query_url(q, tc.params["subauthority"])))
29
+ end
30
+
31
+ # If the subauthority = "all" (though it shouldn't), call the fetch_discogs_results method to determine
32
+ # whether the id matches a release or master. And if the requested format is json-ld, call the build_graph
33
+ # method in the translation module; otherwise, just return the Discogs json. check the response to
34
+ # determine if it should go to the translation module.
35
+ #
36
+ # @param [String] the Discogs id of the selected item
37
+ # @param [Class] QA::TermsController
38
+ # @return either json results or jsonld
39
+ def find(id, tc)
40
+ response = tc.params["subauthority"].include?("all") ? fetch_discogs_results(id) : json(find_url(id, tc.params["subauthority"]))
41
+ return build_graph(response) unless tc.params["format"] != "jsonld" || response["message"].present?
42
+ response
43
+ end
44
+
45
+ # @param [String] the query
46
+ # @param [String] the subauthority
47
+ # @return [String] the url
48
+ def build_query_url(q, subauthority)
49
+ escaped_q = ERB::Util.url_encode(q)
50
+ "https://api.discogs.com/database/search?q=#{escaped_q}&type=#{subauthority}&key=#{discogs_key}&secret=#{discogs_secret}"
51
+ end
52
+
53
+ # @param [String] the id of the selected item
54
+ # @param [String] the subauthority
55
+ # @return [String] the url
56
+ def find_url(id, subauthority)
57
+ "https://api.discogs.com/#{subauthority}s/#{id}"
58
+ end
59
+
60
+ private
61
+
62
+ # In the unusual case that we have an id and the subauthority is "all", we don't know which Discogs url to
63
+ # use. If the id is a match for both a release and a master (or neither), return that info as the
64
+ # message. Otherwise, return the data for the release or master.
65
+ # @param [String] the id of the selected item
66
+ # @return json results
67
+ def fetch_discogs_results(id)
68
+ release_resp = json(find_url(id, "release"))
69
+ master_resp = json(find_url(id, "master"))
70
+ message_status = check_for_msg_response(release_resp, master_resp)
71
+
72
+ return { "message" => "Neither a master nor a release matches the requested ID." } if message_status == "no responses"
73
+ if message_status == "two responses"
74
+ return { "message" => "Both a master and a release match the requested ID.",
75
+ "resource_url" => ["https://api.discogs.com/masters/#{id}", "https://api.discogs.com/releases/#{id}"] }
76
+ end
77
+ return master_resp unless master_resp.key?("message")
78
+ # return release_resp unless release_resp.key?("message")
79
+ release_resp
80
+ end
81
+
82
+ # @param json results
83
+ # @param json results
84
+ # @return [String] status information
85
+ def check_for_msg_response(release_resp, master_resp)
86
+ if release_resp.key?("message") && master_resp.key?("message")
87
+ "no responses"
88
+ elsif !release_resp.key?("message") && !master_resp.key?("message")
89
+ "two responses"
90
+ else
91
+ "mixed"
92
+ end
93
+ end
94
+
95
+ # @param [Hash] the http response from discogs
96
+ # @example returns parsed discogs data with context
97
+ # {
98
+ # "uri": "https://api.discogs.com/releases/4212473",
99
+ # "id": "4212473",
100
+ # "label": "Frank Sinatra And The Modernaires - Sorry / Why Remind Me",
101
+ # }
102
+ # "context": {
103
+ # "Image URL": [
104
+ # "https://img.discogs.com/2e-YoNr0dvmMgbzEN0hjHD6X0sU=/fit-in/600x580/filters:strip_icc():format(jpeg):mode_rgb():quality(90)/discogs-images/R-4212473-1358693671-5430.jpeg.jpg"
105
+ # ],
106
+ # "Year": [
107
+ # "1950"
108
+ # ],
109
+ # "Record Labels": [
110
+ # "Columbia"
111
+ # ],
112
+ # "Formats": [
113
+ # "Shellac",
114
+ # "10\"",
115
+ # "78 RPM"
116
+ # ],
117
+ # "Type": [
118
+ # "release"
119
+ # ]
120
+ # }
121
+ def parse_authority_response(response)
122
+ response['results'].map do |result|
123
+ { 'uri' => result['resource_url'].to_s,
124
+ 'id' => result['id'].to_s,
125
+ 'label' => result['title'].to_s,
126
+ 'context' => assemble_search_context(result) }
127
+ end
128
+ end
129
+
130
+ # @param [Hash] the results hash from the JSON returned by Discogs
131
+ def assemble_search_context(result)
132
+ { "Image URL" => get_context_for_string(result['cover_image']),
133
+ "Year" => get_context_for_string(result['year']),
134
+ "Record Labels" => get_context_for_array(result['label']),
135
+ "Formats" => get_context_for_array(result['format']),
136
+ "Type" => get_context_for_string(result['type']) }
137
+ end
138
+
139
+ # checks if the param is null, returns appropriate value
140
+ # @param [String] returns an empty string if item is not presentr
141
+ def get_context_for_string(item)
142
+ [item.present? ? item.to_s : ""]
143
+ end
144
+
145
+ # checks if the param is null, returns appropriate value
146
+ # @param [Array] returns an empty array if item is not presentr
147
+ def get_context_for_array(item)
148
+ item.present? ? item : [""]
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,9 @@
1
+ module Qa::Authorities::DiscogsSubauthority
2
+ def authorities
3
+ [
4
+ "master",
5
+ "release",
6
+ "all"
7
+ ]
8
+ end
9
+ end
@@ -28,11 +28,11 @@ module Qa::Authorities
28
28
  end
29
29
 
30
30
  def search
31
- @search ||= Qa::Authorities::LinkedData::SearchConfig.new(authority_config.fetch(:search), prefixes)
31
+ @search ||= Qa::Authorities::LinkedData::SearchConfig.new(authority_config.fetch(:search), prefixes, self)
32
32
  end
33
33
 
34
34
  def term
35
- @term ||= Qa::Authorities::LinkedData::TermConfig.new(authority_config.fetch(:term), prefixes)
35
+ @term ||= Qa::Authorities::LinkedData::TermConfig.new(authority_config.fetch(:term), prefixes, self)
36
36
  end
37
37
 
38
38
  def prefixes
@@ -47,6 +47,10 @@ module Qa::Authorities
47
47
  config_version == version
48
48
  end
49
49
 
50
+ def authority_info
51
+ search.info + term.info
52
+ end
53
+
50
54
  # Return the full configuration for an authority
51
55
  # @return [String] the authority configuration
52
56
  def authority_config
@@ -79,7 +83,7 @@ module Qa::Authorities
79
83
  def convert_1_0_url_to_2_0_url(action_key)
80
84
  url_template = @authority_config.fetch(action_key, {}).fetch(:url, {}).fetch(:template, "")
81
85
  return if url_template.blank?
82
- warn "[DEPRECATED] #Linked data configuration #{authority_name} has 1.0 version format which is deprecated; update to version 2.0 configuration."
86
+ Qa.deprecation_warning(msg: "Linked data configuration #{authority_name} has 1.0 version format which is deprecated; update to version 2.0 configuration.")
83
87
  @authority_config[action_key][:url][:template] = url_template.gsub("{?", "{")
84
88
  end
85
89
  end
@@ -4,18 +4,21 @@
4
4
  # @see Qa::Authorities::LinkedData::TermConfig
5
5
  module Qa::Authorities
6
6
  module LinkedData
7
- class SearchConfig
8
- attr_reader :prefixes
7
+ class SearchConfig # rubocop:disable Metrics/ClassLength
8
+ attr_reader :prefixes, :full_config, :search_config
9
+ private :full_config, :search_config
10
+
11
+ delegate :authority_name, to: :full_config
9
12
 
10
13
  # @param [Hash] config the search portion of the config
11
- def initialize(config, prefixes = {})
14
+ # @param [Hash<Symbol><String>] prefixes URL map of prefixes to use with ldpaths
15
+ # @param [Qa::Authorities::LinkedData::Config] full_config the full linked data configuration that the passed in search config is part of
16
+ def initialize(config, prefixes = {}, full_config = nil)
12
17
  @search_config = config
13
18
  @prefixes = prefixes
19
+ @full_config = full_config
14
20
  end
15
21
 
16
- attr_reader :search_config
17
- private :search_config
18
-
19
22
  # Does this authority configuration have search defined?
20
23
  # @return [Boolean] true if search is configured; otherwise, false
21
24
  def supports_search?
@@ -29,6 +32,7 @@ module Qa::Authorities
29
32
  end
30
33
 
31
34
  # Return the preferred language for literal value selection for search query.
35
+ # This is the default used for this authority if the user does not pass in a language.
32
36
  # Only applies if the authority provides language encoded literals.
33
37
  # @return [String] the configured language for search query
34
38
  def language
@@ -39,40 +43,80 @@ module Qa::Authorities
39
43
  @language = lang.collect(&:to_sym)
40
44
  end
41
45
 
42
- # Return results predicates if specified
43
- # @return [Hash,NilClass] all the configured predicates to pull out of the results
46
+ # Return results ldpaths or predicates if specified
47
+ # @return [Hash,NilClass] all the configured ldpaths or predicates to pull out of the results
44
48
  def results
45
49
  search_config[:results]
46
50
  end
47
51
 
52
+ # Return results id_ldpath
53
+ # @return [String] the configured ldpath to use to extract the id from the results
54
+ def results_id_ldpath
55
+ Config.config_value(results, :id_ldpath)
56
+ end
57
+
48
58
  # Return results id_predicate
49
59
  # @return [String] the configured predicate to use to extract the id from the results
50
60
  def results_id_predicate
61
+ Qa.deprecation_warning(
62
+ in_msg: 'Qa::Authorities::LinkedData::SearchConfig',
63
+ msg: "`results_id_predicate` is deprecated; use `results_id_ldpath` by updating linked data search config results to specify as `id_ldpath`"
64
+ )
51
65
  Config.predicate_uri(results, :id_predicate)
52
66
  end
53
67
 
68
+ # Return results label_ldpath
69
+ # @return [String] the configured ldpath to use to extract label values from the results
70
+ def results_label_ldpath
71
+ Config.config_value(results, :label_ldpath)
72
+ end
73
+
54
74
  # Return results label_predicate
55
75
  # @return [String] the configured predicate to use to extract label values from the results
56
76
  def results_label_predicate
77
+ Qa.deprecation_warning(
78
+ in_msg: 'Qa::Authorities::LinkedData::SearchConfig',
79
+ msg: "`results_label_predicate` is deprecated; use `results_label_ldpath` by updating linked data search config results to specify as `label_ldpath`"
80
+ )
57
81
  Config.predicate_uri(results, :label_predicate)
58
82
  end
59
83
 
84
+ # Return results altlabel_ldpath
85
+ # @return [String] the configured ldpath to use to extract altlabel values from the results
86
+ def results_altlabel_ldpath
87
+ Config.config_value(results, :altlabel_ldpath)
88
+ end
89
+
60
90
  # Return results altlabel_predicate
61
91
  # @return [String] the configured predicate to use to extract altlabel values from the results
62
92
  def results_altlabel_predicate
93
+ Qa.deprecation_warning(
94
+ in_msg: 'Qa::Authorities::LinkedData::SearchConfig',
95
+ msg: "`results_altlabel_predicate` is deprecated; use `results_altlabel_ldpath` by updating linked data search config results to specify as `altlabel_ldpath`"
96
+ )
63
97
  Config.predicate_uri(results, :altlabel_predicate)
64
98
  end
65
99
 
66
100
  # Does this authority configuration support sorting of search results?
67
101
  # @return [True|False] true if sorting of search results is supported; otherwise, false
68
102
  def supports_sort?
69
- return true unless results_sort_predicate.nil? || !results_sort_predicate.size.positive?
103
+ return true unless results_sort_ldpath.present? || !results_sort_predicate.present?
70
104
  false
71
105
  end
72
106
 
107
+ # Return results sort_ldpath
108
+ # @return [String] the configured ldpath to use for sorting results from the query search
109
+ def results_sort_ldpath
110
+ Config.config_value(results, :sort_ldpath)
111
+ end
112
+
73
113
  # Return results sort_predicate
74
114
  # @return [String] the configured predicate to use for sorting results from the query search
75
115
  def results_sort_predicate
116
+ Qa.deprecation_warning(
117
+ in_msg: 'Qa::Authorities::LinkedData::SearchConfig',
118
+ msg: "`results_sort_predicate` is deprecated; use `results_sort_ldpath` by updating linked data search config results to specify as `sort_ldpath`"
119
+ )
76
120
  Config.predicate_uri(results, :sort_predicate)
77
121
  end
78
122
 
@@ -90,10 +134,20 @@ module Qa::Authorities
90
134
  @context_map ||= Qa::LinkedData::Config::ContextMap.new(search_config.fetch(:context), prefixes)
91
135
  end
92
136
 
93
- # Return parameters that are required for QA api
137
+ # Return parameters that are supported directly by QA api (e.g. q, subauth, lang)
94
138
  # @return [Hash] the configured search url parameter mappings
95
139
  def qa_replacement_patterns
96
- search_config.fetch(:qa_replacement_patterns)
140
+ search_config.fetch(:qa_replacement_patterns, {})
141
+ end
142
+
143
+ # @return [Boolean] true if supports language parameter; otherwise, false
144
+ def supports_subauthorities?
145
+ qa_replacement_patterns.key?(:subauth) && subauthorities?
146
+ end
147
+
148
+ # @return [Boolean] true if supports language parameter; otherwise, false
149
+ def supports_language_parameter?
150
+ qa_replacement_patterns.key? :lang
97
151
  end
98
152
 
99
153
  # Are there subauthorities configured for search query?
@@ -121,6 +175,40 @@ module Qa::Authorities
121
175
  @subauthorities ||= {} if search_config.nil? || !(search_config.key? :subauthorities)
122
176
  @subauthorities ||= search_config.fetch(:subauthorities)
123
177
  end
178
+
179
+ def info
180
+ return [] unless supports_search?
181
+ auth_name = authority_name.downcase.to_s
182
+ language = Qa::LinkedData::LanguageService.preferred_language(authority_language: language).map(&:to_s)
183
+ details = summary_without_subauthority(auth_name, language)
184
+ subauthorities.each_key { |subauth_name| details << summary_with_subauthority(auth_name, subauth_name.downcase.to_s, language) }
185
+ details
186
+ end
187
+
188
+ private
189
+
190
+ def summary_without_subauthority(auth_name, language)
191
+ [
192
+ {
193
+ "label" => "#{auth_name} search (QA)",
194
+ "uri" => "urn:qa:search:#{auth_name}",
195
+ "authority" => auth_name,
196
+ "action" => "search",
197
+ "language" => language
198
+ }
199
+ ]
200
+ end
201
+
202
+ def summary_with_subauthority(auth_name, subauth_name, language)
203
+ {
204
+ "label" => "#{auth_name} search #{subauth_name} (QA)",
205
+ "uri" => "urn:qa:search:#{auth_name}:#{subauth_name}",
206
+ "authority" => auth_name,
207
+ "subauthority" => subauth_name,
208
+ "action" => "search",
209
+ "language" => language
210
+ }
211
+ end
124
212
  end
125
213
  end
126
214
  end
@@ -5,15 +5,20 @@
5
5
  module Qa::Authorities
6
6
  module LinkedData
7
7
  class TermConfig
8
+ attr_reader :prefixes, :full_config, :term_config
9
+ private :full_config, :term_config
10
+
11
+ delegate :authority_name, to: :full_config
12
+
8
13
  # @param [Hash] config the term portion of the config
9
- def initialize(config, prefixes = {})
14
+ # @param [Hash<Symbol><String>] prefixes URL map of prefixes to use with ldpaths
15
+ # @param [Qa::Authorities::LinkedData::Config] full_config the full linked data configuration that the passed in search config is part of
16
+ def initialize(config, prefixes = {}, full_config = nil)
10
17
  @term_config = config
11
18
  @prefixes = prefixes
19
+ @full_config = full_config
12
20
  end
13
21
 
14
- attr_reader :term_config
15
- private :term_config
16
-
17
22
  # Does this authority configuration have term defined?
18
23
  # @return [True|False] true if term fetching is configured; otherwise, false
19
24
  def supports_term?
@@ -41,6 +46,8 @@ module Qa::Authorities
41
46
  end
42
47
 
43
48
  # Return the preferred language for literal value selection for term fetch. Only applies if the authority provides language encoded literals.
49
+ # This is the default used for this authority if the user does not pass in a language.
50
+ # Only applies if the authority provides language encoded literals.
44
51
  # @return [Symbol] the configured language for term fetch (default - :en)
45
52
  def term_language
46
53
  return @term_language unless @term_language.nil?
@@ -49,17 +56,33 @@ module Qa::Authorities
49
56
  lang = [lang] if lang.is_a? String
50
57
  @term_language = lang.collect(&:to_sym)
51
58
  end
59
+ alias language term_language
52
60
 
53
- # Return results predicates
54
- # @return [Hash] all the configured predicates to pull out of the results
61
+ # Return results ldpaths or predicates
62
+ # @return [Hash] all the configured ldpaths or predicates to pull out of the results
55
63
  def term_results
56
64
  Config.config_value(term_config, :results)
57
65
  end
58
66
 
67
+ # Return results id_ldpath
68
+ # @return [String] the configured ldpath to use to extract the id from the results
69
+ def term_results_id_ldpath
70
+ Config.config_value(term_results, :id_ldpath)
71
+ end
72
+
59
73
  # Return results id_predicate
60
74
  # @return [String] the configured predicate to use to extract the id from the results
61
75
  def term_results_id_predicate
62
- Config.predicate_uri(term_results, :id_predicate)
76
+ return @pred_id unless @pred_id.blank?
77
+ @pred_id = Config.predicate_uri(term_results, :id_predicate)
78
+ return @pred_id unless @pred_id.blank?
79
+ @pred_id = pred_id_from_ldpath
80
+ end
81
+
82
+ # Return results label_ldpath
83
+ # @return [String] the configured ldpath to use to extract label values from the results
84
+ def term_results_label_ldpath
85
+ Config.config_value(term_results, :label_ldpath)
63
86
  end
64
87
 
65
88
  # Return results label_predicate
@@ -68,24 +91,48 @@ module Qa::Authorities
68
91
  Config.predicate_uri(term_results, :label_predicate)
69
92
  end
70
93
 
94
+ # Return results altlabel_ldpath
95
+ # @return [String] the configured ldpath to use to extract altlabel values from the results
96
+ def term_results_altlabel_ldpath
97
+ Config.config_value(term_results, :altlabel_ldpath)
98
+ end
99
+
71
100
  # Return results altlabel_predicate
72
101
  # @return [String] the configured predicate to use to extract altlabel values from the results
73
102
  def term_results_altlabel_predicate
74
103
  Config.predicate_uri(term_results, :altlabel_predicate)
75
104
  end
76
105
 
106
+ # Return results broader_ldpath
107
+ # @return [String] the configured ldpath to use to extract URIs for broader terms from the results
108
+ def term_results_broader_ldpath
109
+ Config.config_value(term_results, :broader_ldpath)
110
+ end
111
+
77
112
  # Return results broader_predicate
78
113
  # @return [String] the configured predicate to use to extract URIs for broader terms from the results
79
114
  def term_results_broader_predicate
80
115
  Config.predicate_uri(term_results, :broader_predicate)
81
116
  end
82
117
 
118
+ # Return results narrower_ldpath
119
+ # @return [String] the configured ldpath to use to extract URIs for narrower terms from the results
120
+ def term_results_narrower_ldpath
121
+ Config.config_value(term_results, :narrower_ldpath)
122
+ end
123
+
83
124
  # Return results narrower_predicate
84
125
  # @return [String] the configured predicate to use to extract URIs for narrower terms from the results
85
126
  def term_results_narrower_predicate
86
127
  Config.predicate_uri(term_results, :narrower_predicate)
87
128
  end
88
129
 
130
+ # Return results sameas_ldpath
131
+ # @return [String] the configured ldpath to use to extract URIs for sameas terms from the results
132
+ def term_results_sameas_ldpath
133
+ Config.config_value(term_results, :sameas_ldpath)
134
+ end
135
+
89
136
  # Return results sameas_predicate
90
137
  # @return [String] the configured predicate to use to extract URIs for sameas terms from the results
91
138
  def term_results_sameas_predicate
@@ -95,15 +142,26 @@ module Qa::Authorities
95
142
  # Return parameters that are required for QA api
96
143
  # @return [Hash] the configured term url parameter mappings
97
144
  def term_qa_replacement_patterns
98
- Config.config_value(term_config, :qa_replacement_patterns)
145
+ term_config.fetch(:qa_replacement_patterns, {})
99
146
  end
100
147
  alias qa_replacement_patterns term_qa_replacement_patterns
101
148
 
149
+ # @return [Boolean] true if supports language parameter; otherwise, false
150
+ def supports_subauthorities?
151
+ qa_replacement_patterns.key?(:subauth) && subauthorities?
152
+ end
153
+
154
+ # @return [Boolean] true if supports language parameter; otherwise, false
155
+ def supports_language_parameter?
156
+ qa_replacement_patterns.key? :lang
157
+ end
158
+
102
159
  # Are there subauthorities configured for term fetch?
103
160
  # @return [True|False] true if there are subauthorities configured term fetch; otherwise, false
104
161
  def term_subauthorities?
105
162
  term_subauthority_count.positive?
106
163
  end
164
+ alias subauthorities? term_subauthorities?
107
165
 
108
166
  # Is a specific subauthority configured for term fetch?
109
167
  # @return [True|False] true if the specified subauthority is configured for term fetch; otherwise, false
@@ -125,6 +183,52 @@ module Qa::Authorities
125
183
  @term_subauthorities ||= term_config[:subauthorities]
126
184
  end
127
185
  alias subauthorities term_subauthorities
186
+
187
+ def info
188
+ return [] unless supports_term?
189
+ auth_name = authority_name.downcase.to_s
190
+ language = Qa::LinkedData::LanguageService.preferred_language(authority_language: language).map(&:to_s)
191
+ details = summary_without_subauthority(auth_name, language)
192
+ subauthorities.keys { |subauth_name| details << summary_with_subauthority(auth_name, subauth_name.downcase.to_s, language) }
193
+ details
194
+ end
195
+
196
+ private
197
+
198
+ def pred_id_from_ldpath
199
+ # prefix example: { skos: 'http://www.w3.org/2004/02/skos/core#' }
200
+ # ldpath example: 'skos:id :: xsd:string'
201
+ id_ldpath = term_results_id_ldpath
202
+ return nil if id_ldpath.blank?
203
+ tokens = id_ldpath.split(':')
204
+ return nil if tokens.size < 2
205
+ prefix = tokens.first.to_sym
206
+ prefix_path = prefixes[prefix]
207
+ prefix_path + tokens.second.strip
208
+ end
209
+
210
+ def summary_without_subauthority(auth_name, language)
211
+ [
212
+ {
213
+ "label" => "#{auth_name} term (QA)",
214
+ "uri" => "urn:qa:term:#{auth_name}",
215
+ "authority" => auth_name,
216
+ "action" => "term",
217
+ "language" => language
218
+ }
219
+ ]
220
+ end
221
+
222
+ def summary_with_subauthority(auth_name, subauth_name, language)
223
+ {
224
+ "label" => "#{auth_name} term #{subauth_name} (QA)",
225
+ "uri" => "urn:qa:term:#{auth_name}:#{subauth_name}",
226
+ "authority" => auth_name,
227
+ "subauthority" => subauth_name,
228
+ "action" => "term",
229
+ "language" => language
230
+ }
231
+ end
128
232
  end
129
233
  end
130
234
  end