qa 3.1.0 → 4.0.0.rc1

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 (95) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +16 -548
  3. data/app/controllers/qa/linked_data_terms_controller.rb +64 -42
  4. data/app/controllers/qa/terms_controller.rb +14 -6
  5. data/app/models/qa/iri_template/url_config.rb +47 -0
  6. data/app/models/qa/iri_template/variable_map.rb +62 -0
  7. data/app/models/qa/linked_data/config/context_map.rb +77 -0
  8. data/app/models/qa/linked_data/config/context_property_map.rb +144 -0
  9. data/app/models/qa/linked_data/config/helper.rb +34 -0
  10. data/app/services/qa/iri_template_service.rb +31 -0
  11. data/{lib/qa/authorities → app/services/qa}/linked_data/authority_service.rb +3 -4
  12. data/app/services/qa/linked_data/authority_url_service.rb +48 -0
  13. data/app/services/qa/linked_data/deep_sort_service.rb +238 -0
  14. data/app/services/qa/linked_data/graph_service.rb +106 -0
  15. data/app/services/qa/linked_data/language_service.rb +30 -0
  16. data/app/services/qa/linked_data/language_sort_service.rb +81 -0
  17. data/app/services/qa/linked_data/mapper/context_mapper_service.rb +59 -0
  18. data/app/services/qa/linked_data/mapper/graph_mapper_service.rb +40 -0
  19. data/app/services/qa/linked_data/mapper/search_results_mapper_service.rb +70 -0
  20. data/config/authorities/linked_data/loc.json +5 -2
  21. data/config/authorities/linked_data/oclc_fast.json +3 -2
  22. data/config/initializers/linked_data_authorities.rb +1 -1
  23. data/config/locales/qa.en.yml +9 -0
  24. data/lib/generators/qa/install/templates/config/initializers/qa.rb +4 -0
  25. data/lib/qa.rb +8 -0
  26. data/lib/qa/authorities/assign_fast/generic_authority.rb +1 -1
  27. data/lib/qa/authorities/base.rb +0 -11
  28. data/lib/qa/authorities/crossref/generic_authority.rb +1 -1
  29. data/lib/qa/authorities/geonames.rb +1 -1
  30. data/lib/qa/authorities/getty/aat.rb +7 -2
  31. data/lib/qa/authorities/getty/tgn.rb +7 -2
  32. data/lib/qa/authorities/getty/ulan.rb +7 -2
  33. data/lib/qa/authorities/linked_data.rb +0 -1
  34. data/lib/qa/authorities/linked_data/config.rb +29 -28
  35. data/lib/qa/authorities/linked_data/config/search_config.rb +21 -79
  36. data/lib/qa/authorities/linked_data/config/term_config.rb +7 -77
  37. data/lib/qa/authorities/linked_data/find_term.rb +25 -17
  38. data/lib/qa/authorities/linked_data/generic_authority.rb +6 -5
  39. data/lib/qa/authorities/linked_data/rdf_helper.rb +6 -73
  40. data/lib/qa/authorities/linked_data/search_query.rb +54 -101
  41. data/lib/qa/authorities/loc/generic_authority.rb +4 -4
  42. data/lib/qa/authorities/web_service_base.rb +1 -8
  43. data/lib/qa/configuration.rb +7 -0
  44. data/lib/qa/version.rb +1 -1
  45. data/lib/tasks/mesh.rake +19 -18
  46. data/spec/controllers/linked_data_terms_controller_spec.rb +51 -1
  47. data/spec/controllers/terms_controller_spec.rb +15 -15
  48. data/spec/fixtures/authorities/linked_data/lod_encoding_config.json +2 -1
  49. data/spec/fixtures/authorities/linked_data/lod_full_config.json +56 -2
  50. data/spec/fixtures/authorities/linked_data/lod_full_config_1_0.json +164 -0
  51. data/spec/fixtures/authorities/linked_data/lod_lang_defaults.json +5 -4
  52. data/spec/fixtures/authorities/linked_data/lod_lang_multi_defaults.json +3 -2
  53. data/spec/fixtures/authorities/linked_data/lod_lang_no_defaults.json +3 -2
  54. data/spec/fixtures/authorities/linked_data/lod_lang_param.json +3 -2
  55. data/spec/fixtures/authorities/linked_data/lod_min_config.json +3 -2
  56. data/spec/fixtures/authorities/linked_data/lod_search_only_config.json +2 -1
  57. data/spec/fixtures/authorities/linked_data/lod_sort.json +2 -1
  58. data/spec/fixtures/authorities/linked_data/lod_term_id_param_config.json +2 -1
  59. data/spec/fixtures/authorities/linked_data/lod_term_only_config.json +2 -1
  60. data/spec/fixtures/authorities/linked_data/lod_term_uri_param_config.json +2 -1
  61. data/spec/fixtures/getty-error-response.txt +10 -0
  62. data/spec/fixtures/lod_2_ranked_2_unranked.nt +17 -0
  63. data/spec/fixtures/lod_3_ranked_varying_preds.nt +16 -0
  64. data/spec/fixtures/lod_lang_search_filtering.nt +11 -0
  65. data/spec/fixtures/lod_search_with_blanknode_subjects.nt +18 -0
  66. data/spec/fixtures/lod_term_with_blanknode_objects.nt +8 -0
  67. data/spec/lib/authorities/assign_fast_spec.rb +1 -0
  68. data/spec/lib/authorities/getty/aat_spec.rb +14 -2
  69. data/spec/lib/authorities/getty/tgn_spec.rb +14 -2
  70. data/spec/lib/authorities/getty/ulan_spec.rb +14 -2
  71. data/spec/lib/authorities/linked_data/authority_service_spec.rb +2 -1
  72. data/spec/lib/authorities/linked_data/config_spec.rb +284 -5
  73. data/spec/lib/authorities/linked_data/find_term_spec.rb +3 -1
  74. data/spec/lib/authorities/linked_data/generic_authority_spec.rb +92 -42
  75. data/spec/lib/authorities/linked_data/search_config_spec.rb +67 -160
  76. data/spec/lib/authorities/linked_data/search_query_spec.rb +3 -127
  77. data/spec/lib/authorities/linked_data/term_config_spec.rb +6 -134
  78. data/spec/lib/authorities/loc_spec.rb +9 -9
  79. data/spec/lib/configuration_spec.rb +20 -7
  80. data/spec/lib/tasks/mesh.rake_spec.rb +2 -2
  81. data/spec/models/iri_template/url_config_spec.rb +102 -0
  82. data/spec/models/iri_template/variable_map_spec.rb +105 -0
  83. data/spec/models/linked_data/config/context_map_spec.rb +148 -0
  84. data/spec/models/linked_data/config/context_property_map_spec.rb +286 -0
  85. data/spec/services/iri_template_service_spec.rb +69 -0
  86. data/spec/services/linked_data/authority_url_service_spec.rb +107 -0
  87. data/spec/services/linked_data/deep_sort_service_spec.rb +260 -0
  88. data/spec/services/linked_data/graph_service_spec.rb +232 -0
  89. data/spec/services/linked_data/language_service_spec.rb +66 -0
  90. data/spec/services/linked_data/language_sort_service_spec.rb +58 -0
  91. data/spec/services/linked_data/mapper/context_mapper_service_spec.rb +137 -0
  92. data/spec/services/linked_data/mapper/graph_mapper_service_spec.rb +110 -0
  93. data/spec/services/linked_data/mapper/search_results_mapper_service_spec.rb +109 -0
  94. data/spec/spec_helper.rb +10 -2
  95. metadata +81 -11
@@ -0,0 +1,30 @@
1
+ # Service to determine which language to use for sorting and filtering.
2
+ module Qa
3
+ module LinkedData
4
+ class LanguageService
5
+ class << self
6
+ def preferred_language(user_language: nil, authority_language: nil)
7
+ return normalize_language(user_language) if user_language.present?
8
+ return normalize_language(authority_language) if authority_language.present?
9
+ normalize_language(Qa.config.default_language)
10
+ end
11
+
12
+ def literal_has_language_marker?(literal)
13
+ return false unless literal.respond_to?(:language)
14
+ literal.language.present?
15
+ end
16
+
17
+ private
18
+
19
+ # Normalize language
20
+ # @param [String | Symbol | Array] language for filtering graph (e.g. "en" OR :en OR ["en", "fr"] OR [:en, :fr])
21
+ # @return [Array<Symbol>] an array of languages encoded as symbols (e.g. [:en] OR [:en, :fr])
22
+ def normalize_language(language)
23
+ return language if language.blank?
24
+ language = [language] unless language.is_a? Array
25
+ language.map(&:to_sym)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,81 @@
1
+ # Service to sort an array of literals by language and within language.
2
+ module Qa
3
+ module LinkedData
4
+ class LanguageSortService
5
+ LANGUAGE_LOCALE_KEY_FOR_NO_LANGUAGE = :NO_LANGUAGE
6
+
7
+ attr_reader :literals, :preferred_language
8
+ attr_reader :languages, :bins
9
+ private :literals, :preferred_language, :languages, :bins
10
+ # private :literals, :preferred_language, :languages, :languages=, :bins, :bins=
11
+
12
+ # @param [Array<RDF::Literals>] string literals to sort
13
+ # @param [Symbol] preferred language to appear first in the list; defaults to no preference
14
+ # @return instance of this class
15
+ def initialize(literals, preferred_language = nil)
16
+ @literals = literals
17
+ @preferred_language = preferred_language
18
+ @languages = []
19
+ @bins = {}
20
+ end
21
+
22
+ # Sort the literals stored in this instance of the service
23
+ # @return sorted version of literals
24
+ def sort
25
+ return literals unless literals.present?
26
+ return @sorted_literals if @sorted_literals.present?
27
+ parse_into_language_bins
28
+ sort_languages
29
+ sort_language_bins
30
+ @sorted_literals = construct_sorted_literals
31
+ end
32
+
33
+ private
34
+
35
+ def construct_sorted_literals
36
+ sorted_literals = []
37
+ 0.upto(languages.size - 1) { |idx| sorted_literals.concat(bins[languages[idx]]) }
38
+ sorted_literals
39
+ end
40
+
41
+ def language(literal)
42
+ return LANGUAGE_LOCALE_KEY_FOR_NO_LANGUAGE unless Qa::LinkedData::LanguageService.literal_has_language_marker? literal
43
+ literal.language
44
+ end
45
+
46
+ def move_no_language_to_end
47
+ return unless languages.include?(LANGUAGE_LOCALE_KEY_FOR_NO_LANGUAGE)
48
+ languages.delete(LANGUAGE_LOCALE_KEY_FOR_NO_LANGUAGE)
49
+ languages << LANGUAGE_LOCALE_KEY_FOR_NO_LANGUAGE
50
+ end
51
+
52
+ def move_preferred_language_to_front
53
+ return unless preferred_language.present? && languages.include?(preferred_language)
54
+ languages.delete(preferred_language)
55
+ languages.insert(0, preferred_language)
56
+ end
57
+
58
+ def parse_into_language_bins
59
+ 0.upto(literals.size - 1) do |idx|
60
+ lang = language(literals[idx])
61
+ languages << lang
62
+ bin = bins.fetch(lang, [])
63
+ bin << literals[idx]
64
+ bins[lang] = bin
65
+ end
66
+ @language = languages
67
+ @bins = bins
68
+ end
69
+
70
+ def sort_languages
71
+ languages.sort!.uniq!
72
+ move_preferred_language_to_front
73
+ move_no_language_to_end
74
+ end
75
+
76
+ def sort_language_bins
77
+ bins.each_value { |bin| bin.sort_by! { |literal| literal.to_s.downcase } }
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,59 @@
1
+ # Provide service for mapping predicates to object values.
2
+ module Qa
3
+ module LinkedData
4
+ module Mapper
5
+ class ContextMapperService
6
+ class_attribute :graph_service
7
+ self.graph_service = Qa::LinkedData::GraphService
8
+
9
+ class << self
10
+ # Extract predicates specified in the predicate_map from the graph and return as a value map for a single subject URI.
11
+ # @param graph [RDF::Graph] the graph from which to extract result values
12
+ # @param context_map [Qa::LinkedData::Config::ContextMap] defines properties to extract from the graph to provide additional context
13
+ # @param subject_uri [RDF::URI] the subject within the graph for which the values are being extracted
14
+ # @return [<Hash<Symbol><Array<Object>>] mapped context values and information with hash of map key = array of object values for predicates identified in predicate_map.
15
+ # @example returned context map with one property defined
16
+ # [{"group" => "group label,
17
+ # "property" => "property label",
18
+ # "values" => ["value 1","value 2"],
19
+ # "selectable" => true,
20
+ # "drillable" => false}]
21
+ def map_context(graph:, context_map:, subject_uri:)
22
+ context = []
23
+ context_map.properties.each do |property_map|
24
+ populated_property_map = populate_property_map(context_map, property_map, graph, subject_uri)
25
+ next if populated_property_map.blank?
26
+ context << populated_property_map
27
+ end
28
+ context
29
+ end
30
+
31
+ private
32
+
33
+ def populate_property_map(context_map, property_map, graph, subject_uri)
34
+ begin
35
+ values = property_values(property_map, graph, subject_uri)
36
+ rescue => e
37
+ values = Qa::LinkedData::Config::ContextPropertyMap::VALUE_ON_ERROR
38
+ error = e.message
39
+ end
40
+
41
+ property_info = {}
42
+ property_info["group"] = context_map.group_label(property_map.group_id) if property_map.group?
43
+ property_info["property"] = property_map.label
44
+ property_info["values"] = values
45
+ property_info["selectable"] = property_map.selectable?
46
+ property_info["drillable"] = property_map.drillable?
47
+ property_info["error"] = error if error.present?
48
+ property_info
49
+ end
50
+
51
+ def property_values(property_map, graph, subject_uri)
52
+ return property_map.expanded_values(graph, subject_uri) if property_map.expand_uri?
53
+ property_map.values(graph, subject_uri)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,40 @@
1
+ # Provide service for mapping predicates to object values.
2
+ module Qa
3
+ module LinkedData
4
+ module Mapper
5
+ class GraphMapperService
6
+ class_attribute :graph_service
7
+ self.graph_service = Qa::LinkedData::GraphService
8
+
9
+ # Extract predicates specified in the predicate_map from the graph and return as a value map for a single subject URI.
10
+ # @param graph [RDF::Graph] the graph from which to extract result values
11
+ # @param predicate_map [Hash<Symbol><String||Symbol>] value either maps to a predicate in the graph or is :subject_uri indicating to use the subject uri as the value
12
+ # @example predicate_map
13
+ # {
14
+ # uri: :subject_uri,
15
+ # id: [#<RDF::URI URI:http://id.loc.gov/vocabulary/identifiers/lccn>],
16
+ # label: [#<RDF::URI URI:http://www.w3.org/2004/02/skos/core#prefLabel>],
17
+ # altlabel: [#<RDF::URI URI:http://www.w3.org/2004/02/skos/core#altLabel>],
18
+ # sort: [#<RDF::URI URI:http://vivoweb.org/ontology/core#rank>]'
19
+ # }
20
+ # @param subject_uri [RDF::URI] the subject within the graph for which the values are being extracted
21
+ # @return [<Hash<Symbol><Array<Object>>] mapped result values with hash of map key = array of object values for predicates identified in predicate_map.
22
+ # @example value map for a single result
23
+ # {:uri=>[#<RDF::URI:0x3fcff54a829c URI:http://id.loc.gov/authorities/names/n2010043281>],
24
+ # :id=>[#<RDF::Literal:0x3fcff4a367b4("n2010043281")>],
25
+ # :label=>[#<RDF::Literal:0x3fcff54a9a98("Valli, Sabrina"@en)>],
26
+ # :altlabel=>[],
27
+ # :sort=>[#<RDF::Literal:0x3fcff54b4c18("2")>]}
28
+ def self.map_values(graph:, predicate_map:, subject_uri:)
29
+ value_map = {}
30
+ predicate_map.each do |key, predicate|
31
+ values = predicate == :subject_uri ? [subject_uri] : graph_service.object_values(graph: graph, subject: subject_uri, predicate: predicate)
32
+ value_map[key] = values
33
+ end
34
+ value_map = yield value_map if block_given?
35
+ value_map
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,70 @@
1
+ # Provide service for mapping graph to json limited to configured fields and context.
2
+ module Qa
3
+ module LinkedData
4
+ module Mapper
5
+ class SearchResultsMapperService
6
+ class_attribute :graph_mapper_service, :deep_sort_service, :context_mapper_service
7
+ self.graph_mapper_service = Qa::LinkedData::Mapper::GraphMapperService
8
+ self.deep_sort_service = Qa::LinkedData::DeepSortService
9
+ self.context_mapper_service = Qa::LinkedData::Mapper::ContextMapperService
10
+
11
+ class << self
12
+ # Extract predicates specified in the predicate_map from the graph and return as an array of value maps for each search result subject URI.
13
+ # If a sort key is present, a subject will only be included in the results if it has a statement with the sort predicate.
14
+ # @param graph [RDF::Graph] the graph from which to extract result values
15
+ # @param predicate_map [Hash<Symbol><String||Symbol>] value either maps to a predicate in the graph or is :subject_uri indicating to use the subject uri as the value
16
+ # @example predicate map
17
+ # {
18
+ # uri: :subject_uri,
19
+ # id: 'http://id.loc.gov/vocabulary/identifiers/lccn',
20
+ # label: 'http://www.w3.org/2004/02/skos/core#prefLabel',
21
+ # altlabel: 'http://www.w3.org/2004/02/skos/core#altLabel',
22
+ # sort: 'http://vivoweb.org/ontology/core#rank'
23
+ # }
24
+ # @param sort_key [Symbol] the key in the predicate map for the value on which to sort
25
+ # @param context_map [Qa::LinkedData::Config::ContextMap] map of additional context to include in the results
26
+ # @return [Array<Hash<Symbol><Array<Object>>>] mapped result values with each result as an element in the array
27
+ # with hash of map key = array of object values for predicates identified in map parameter.
28
+ # @example value map for a single result
29
+ # [
30
+ # {:uri=>[#<RDF::URI:0x3fcff54a829c URI:http://id.loc.gov/authorities/names/n2010043281>],
31
+ # :id=>[#<RDF::Literal:0x3fcff4a367b4("n 2010043281")>],
32
+ # :label=>[#<RDF::Literal:0x3fcff54a9a98("Valli, Sabrina"@en)>],
33
+ # :altlabel=>[],
34
+ # :sort=>[#<RDF::Literal:0x3fcff54b4c18("2")>]}
35
+ # ]
36
+ def map_values(graph:, predicate_map:, sort_key:, preferred_language: nil, context_map: nil)
37
+ search_matches = []
38
+ graph.subjects.each do |subject|
39
+ next if subject.anonymous? # skip blank nodes
40
+ values = graph_mapper_service.map_values(graph: graph, predicate_map: predicate_map, subject_uri: subject) do |value_map|
41
+ map_context(graph, sort_key, context_map, value_map, subject)
42
+ end
43
+ search_matches << values if result_subject? values, sort_key
44
+ end
45
+ search_matches = deep_sort_service.new(search_matches, sort_key, preferred_language).sort
46
+ search_matches
47
+ end
48
+
49
+ private
50
+
51
+ # The graph mapper creates the basic value_map for all subject URIs, but we only want the ones that represent search results.
52
+ def result_subject?(value_map, sort_key)
53
+ return true unless sort_key.present? # if sort_key is not defined, then all subjects are considered matches
54
+ return false unless value_map.key? sort_key # otherwise, sort_key must be in the basic value_map
55
+ value_map[sort_key].present? # AND have a value for this to be a search result
56
+ end
57
+
58
+ def map_context(graph, sort_key, context_map, value_map, subject)
59
+ return value_map if context_map.blank?
60
+ return value_map unless result_subject? value_map, sort_key
61
+ context = {}
62
+ context = context_mapper_service.map_context(graph: graph, context_map: context_map, subject_uri: subject) if context_map.present?
63
+ value_map[:context] = context
64
+ value_map
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,9 +1,10 @@
1
1
  {
2
+ "QA_CONFIG_VERSION": "2.0",
2
3
  "term": {
3
4
  "url": {
4
5
  "@context": "http://www.w3.org/ns/hydra/context.jsonld",
5
6
  "@type": "IriTemplate",
6
- "template": "http://id.loc.gov/authorities/{?subauth}/{?term_id}",
7
+ "template": "http://id.loc.gov/authorities/{subauth}/{term_id}",
7
8
  "variableRepresentation": "BasicRepresentation",
8
9
  "mapping": [
9
10
  {
@@ -31,7 +32,9 @@
31
32
  "id_predicate": "http://id.loc.gov/vocabulary/identifiers/lccn",
32
33
  "label_predicate": "http://www.w3.org/2004/02/skos/core#prefLabel",
33
34
  "altlabel_predicate": "http://www.w3.org/2004/02/skos/core#altLabel",
34
- "sameas_predicate": "http://www.w3.org/2004/02/skos/core#exactMatch"
35
+ "sameas_predicate": "http://www.w3.org/2004/02/skos/core#exactMatch",
36
+ "narrower_predicate": "http://www.loc.gov/mads/rdf/v1#hasNarrowerAuthority",
37
+ "broader_predicate": "http://www.loc.gov/mads/rdf/v1#hasBroaderAuthority"
35
38
  },
36
39
  "subauthorities": {
37
40
  "subjects": "subjects",
@@ -1,9 +1,10 @@
1
1
  {
2
+ "QA_CONFIG_VERSION": "2.0",
2
3
  "term": {
3
4
  "url": {
4
5
  "@context": "http://www.w3.org/ns/hydra/context.jsonld",
5
6
  "@type": "IriTemplate",
6
- "template": "http://id.worldcat.org/fast/{?term_id}",
7
+ "template": "http://id.worldcat.org/fast/{term_id}",
7
8
  "variableRepresentation": "BasicRepresentation",
8
9
  "mapping": [
9
10
  {
@@ -29,7 +30,7 @@
29
30
  "url": {
30
31
  "@context": "http://www.w3.org/ns/hydra/context.jsonld",
31
32
  "@type": "IriTemplate",
32
- "template": "http://experimental.worldcat.org/fast/search?query={?subauth}+all+%22{?query}%22&sortKeys=usage&maximumRecords={?maximumRecords}",
33
+ "template": "http://experimental.worldcat.org/fast/search?query={subauth}+all+%22{query}%22&sortKeys=usage&{?maximumRecords}",
33
34
  "variableRepresentation": "BasicRepresentation",
34
35
  "mapping": [
35
36
  {
@@ -1 +1 @@
1
- Qa::Authorities::LinkedData::AuthorityService.load_authorities
1
+ Qa::LinkedData::AuthorityService.load_authorities
@@ -0,0 +1,9 @@
1
+ ---
2
+ en:
3
+ qa:
4
+ linked_data:
5
+ ldpath:
6
+ evaluate_error: LDPATH EVALUATION ERROR (See log for more information)
7
+ evaluate_logger_error: LDPath failed to evaluate the graph with the provided ldpath.
8
+ parse_error: LDPATH PARSE ERROR (See log for more information)
9
+ parse_logger_error: LDPath failed to parse during ldpath program creation.
@@ -10,4 +10,8 @@ Qa.config do |config|
10
10
  # requiring a restart of rails. By default, reloading through the browser is not allowed
11
11
  # when the token is nil or blank. Change to any string to control who has access to reload.
12
12
  # config.authorized_reload_token = 'YOUR_AUTH_TOKEN_DEFINED_HERE'
13
+
14
+ # For linked data access, specify default language for sorting and selection. The default is only used if a language is not
15
+ # specified in the authority's configuration file and not passed in as a parameter. (e.g. :en, [:en], or [:en, :fr])
16
+ # config.default_language = :en
13
17
  end
data/lib/qa.rb CHANGED
@@ -42,6 +42,9 @@ module Qa
42
42
  # Raised when a configuration parameter is incorrect or is required and missing
43
43
  class InvalidConfiguration < ArgumentError; end
44
44
 
45
+ # Raised when a request is made for an unsupported action (e.g. :search, :term are supported)
46
+ class UnsupportedAction < ArgumentError; end
47
+
45
48
  # Raised when a linked data request to a server returns a 503 error
46
49
  class ServiceUnavailable < ArgumentError; end
47
50
 
@@ -50,4 +53,9 @@ module Qa
50
53
 
51
54
  # Raised when the server returns 404 for a find term request
52
55
  class TermNotFound < ArgumentError; end
56
+
57
+ # Raised when a required mapping parameter is missing while building an IRI Template
58
+ module IriTemplate
59
+ class MissingParameter < StandardError; end
60
+ end
53
61
  end
@@ -53,7 +53,7 @@ module Qa::Authorities
53
53
  # See oclc sample code at
54
54
  # http://experimental.worldcat.org/fast/assignfast/js/assignFASTComplete.js
55
55
  def clean_query_string(q)
56
- URI.escape(q.gsub(/-|\(|\)|:/, ""))
56
+ ERB::Util.url_encode(q.gsub(/-|\(|\)|:/, ""))
57
57
  end
58
58
 
59
59
  def parse_authority_response(raw_response)
@@ -1,13 +1,9 @@
1
- require 'deprecation'
2
-
3
1
  module Qa::Authorities
4
2
  ##
5
3
  # @abstract The base class for all authorites. Implementing subclasses must
6
4
  # provide {#all} and #{find} methods.
7
5
  # @todo What about {#search}?
8
6
  class Base
9
- extend Deprecation
10
-
11
7
  ##
12
8
  # @abstract By default, #all is not implemented. A subclass authority must
13
9
  # implement this method to conform to the generic interface.
@@ -33,12 +29,5 @@ module Qa::Authorities
33
29
  def find(_id)
34
30
  raise NotImplementedError, "#{self.class}#find is unimplemented."
35
31
  end
36
-
37
- ##
38
- # @deprecated use {#find} instead
39
- def full_record(id, _subauthority = nil)
40
- Deprecation.warn('#full_record is deprecated. Use #find instead')
41
- find(id)
42
- end
43
32
  end
44
33
  end
@@ -23,7 +23,7 @@ module Qa::Authorities
23
23
  end
24
24
 
25
25
  def build_query_url(q)
26
- query = URI.escape(untaint(q))
26
+ query = ERB::Util.url_encode(untaint(q))
27
27
  "http://api.crossref.org/#{subauthority}?query=#{query}"
28
28
  end
29
29
 
@@ -17,7 +17,7 @@ module Qa::Authorities
17
17
  end
18
18
 
19
19
  def build_query_url(q)
20
- query = URI.escape(untaint(q))
20
+ query = ERB::Util.url_encode(untaint(q))
21
21
  "http://api.geonames.org/searchJSON?q=#{query}&username=#{username}&maxRows=10"
22
22
  end
23
23
 
@@ -7,7 +7,7 @@ module Qa::Authorities
7
7
  end
8
8
 
9
9
  def build_query_url(q)
10
- "http://vocab.getty.edu/sparql.json?query=#{URI.escape(sparql(q))}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
10
+ "http://vocab.getty.edu/sparql.json?query=#{ERB::Util.url_encode(sparql(q))}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
11
11
  end
12
12
 
13
13
  def sparql(q) # rubocop:disable Metrics/MethodLength
@@ -38,7 +38,7 @@ module Qa::Authorities
38
38
  end
39
39
 
40
40
  def find_url(id)
41
- "http://vocab.getty.edu/aat/#{id}.json"
41
+ "http://vocab.getty.edu/download/json?uri=http://vocab.getty.edu/aat/#{id}.json"
42
42
  end
43
43
 
44
44
  def request_options
@@ -52,6 +52,11 @@ module Qa::Authorities
52
52
  response['results']['bindings'].map do |result|
53
53
  { 'id' => result['s']['value'], 'label' => result['name']['value'] }
54
54
  end
55
+ rescue StandardError => e
56
+ cause = response.fetch('error', {}).fetch('cause', 'UNKNOWN')
57
+ cause = cause.present? ? cause : 'UNKNOWN'
58
+ Rails.logger.warn " ERROR fetching Getty response: #{e.message}; cause: #{cause}"
59
+ {}
55
60
  end
56
61
  end
57
62
  end