qa 3.1.0 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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