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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +284 -2
  3. data/app/controllers/qa/linked_data_terms_controller.rb +127 -0
  4. data/config/authorities/linked_data/agrovoc.json +61 -0
  5. data/config/authorities/linked_data/loc.json +46 -0
  6. data/config/authorities/linked_data/oclc_fast.json +78 -0
  7. data/config/initializers/linked_data_authorities.rb +17 -0
  8. data/config/routes.rb +3 -0
  9. data/lib/qa.rb +15 -0
  10. data/lib/qa/authorities.rb +2 -0
  11. data/lib/qa/authorities/base.rb +1 -1
  12. data/lib/qa/authorities/crossref.rb +16 -0
  13. data/lib/qa/authorities/crossref/generic_authority.rb +63 -0
  14. data/lib/qa/authorities/geonames.rb +2 -1
  15. data/lib/qa/authorities/linked_data.rb +10 -0
  16. data/lib/qa/authorities/linked_data/config.rb +80 -0
  17. data/lib/qa/authorities/linked_data/config/search_config.rb +170 -0
  18. data/lib/qa/authorities/linked_data/config/term_config.rb +186 -0
  19. data/lib/qa/authorities/linked_data/find_term.rb +148 -0
  20. data/lib/qa/authorities/linked_data/generic_authority.rb +49 -0
  21. data/lib/qa/authorities/linked_data/rdf_helper.rb +102 -0
  22. data/lib/qa/authorities/linked_data/search_query.rb +143 -0
  23. data/lib/qa/version.rb +1 -1
  24. data/spec/controllers/linked_data_terms_controller_spec.rb +202 -0
  25. data/spec/fixtures/authorities/linked_data/lod_full_config.json +111 -0
  26. data/spec/fixtures/authorities/linked_data/lod_lang_defaults.json +54 -0
  27. data/spec/fixtures/authorities/linked_data/lod_lang_multi_defaults.json +54 -0
  28. data/spec/fixtures/authorities/linked_data/lod_lang_no_defaults.json +52 -0
  29. data/spec/fixtures/authorities/linked_data/lod_lang_param.json +66 -0
  30. data/spec/fixtures/authorities/linked_data/lod_min_config.json +49 -0
  31. data/spec/fixtures/authorities/linked_data/lod_search_only_config.json +55 -0
  32. data/spec/fixtures/authorities/linked_data/lod_sort.json +27 -0
  33. data/spec/fixtures/authorities/linked_data/lod_term_only_config.json +59 -0
  34. data/spec/fixtures/funders-find-response.json +1 -0
  35. data/spec/fixtures/funders-noquery.json +1 -0
  36. data/spec/fixtures/funders-noresults.json +1 -0
  37. data/spec/fixtures/funders-result.json +1 -0
  38. data/spec/fixtures/journals-find-response-two-issn.json +1 -0
  39. data/spec/fixtures/journals-find-response.json +1 -0
  40. data/spec/fixtures/journals-noquery.json +1 -0
  41. data/spec/fixtures/journals-noresults.json +1 -0
  42. data/spec/fixtures/journals-result.json +705 -0
  43. data/spec/fixtures/lod_agrovoc_query_many_results.json +1 -0
  44. data/spec/fixtures/lod_agrovoc_query_no_results.json +1 -0
  45. data/spec/fixtures/lod_agrovoc_term_found.rdf.xml +217 -0
  46. data/spec/fixtures/lod_lang_search_en.rdf.xml +42 -0
  47. data/spec/fixtures/lod_lang_search_enfr.rdf.xml +48 -0
  48. data/spec/fixtures/lod_lang_search_enfrde.rdf.xml +54 -0
  49. data/spec/fixtures/lod_lang_search_fr.rdf.xml +42 -0
  50. data/spec/fixtures/lod_lang_term_en.rdf.xml +65 -0
  51. data/spec/fixtures/lod_lang_term_enfr.rdf.xml +71 -0
  52. data/spec/fixtures/lod_lang_term_enfr_noalt.rdf.xml +69 -0
  53. data/spec/fixtures/lod_lang_term_enfrde.rdf.xml +79 -0
  54. data/spec/fixtures/lod_lang_term_fr.rdf.xml +65 -0
  55. data/spec/fixtures/lod_loc_term_found.rdf.xml +262 -0
  56. data/spec/fixtures/lod_oclc_all_query_3_results.rdf.xml +142 -0
  57. data/spec/fixtures/lod_oclc_personalName_query_3_results.rdf.xml +128 -0
  58. data/spec/fixtures/lod_oclc_query_no_results.rdf.xml +13 -0
  59. data/spec/fixtures/lod_oclc_term_found.rdf.xml +51 -0
  60. data/spec/lib/authorities/crossref_spec.rb +180 -0
  61. data/spec/lib/authorities/geonames_spec.rb +2 -2
  62. data/spec/lib/authorities/linked_data/config_spec.rb +143 -0
  63. data/spec/lib/authorities/linked_data/find_term_spec.rb +5 -0
  64. data/spec/lib/authorities/linked_data/generic_authority_spec.rb +580 -0
  65. data/spec/lib/authorities/linked_data/search_config_spec.rb +385 -0
  66. data/spec/lib/authorities/linked_data/search_query_spec.rb +79 -0
  67. data/spec/lib/authorities/linked_data/term_config_spec.rb +419 -0
  68. data/spec/routing/linked_data_route_spec.rb +35 -0
  69. data/spec/spec_helper.rb +2 -0
  70. metadata +184 -39
@@ -0,0 +1,186 @@
1
+ # Provide attr_reader methods specific to term 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::SearchConfig
5
+ module Qa::Authorities
6
+ module LinkedData
7
+ class TermConfig
8
+ # @param [Hash] config the term portion of the config
9
+ def initialize(config)
10
+ @term_config = config
11
+ end
12
+
13
+ attr_reader :term_config
14
+ private :term_config
15
+
16
+ # Does this authority configuration have term defined?
17
+ # @return [True|False] true if term fetching is configured; otherwise, false
18
+ def supports_term?
19
+ term_config.present?
20
+ end
21
+
22
+ # Return term url encoding defined in the configuration for this authority.
23
+ # @return [Hash] the configured term url
24
+ def term_url
25
+ Config.config_value(term_config, :url)
26
+ end
27
+
28
+ # Return term url template defined in the configuration for this authority.
29
+ # @return [String] the configured term url template
30
+ def term_url_template
31
+ Config.config_value(term_url, :template)
32
+ end
33
+
34
+ # Return term url parameter mapping defined in the configuration for this authority.
35
+ # @return [Hash] the configured term url parameter mappings with variable name as key
36
+ def term_url_mappings
37
+ return @term_url_mappings unless @term_url_mappings.nil?
38
+ mappings = Config.config_value(term_url, :mapping)
39
+ return {} if mappings.nil?
40
+ Hash[*mappings.collect { |m| [m[:variable].to_sym, m] }.flatten]
41
+ end
42
+
43
+ # Is the term_id substitution expected to be a URI?
44
+ # @return [True|False] true if the id substitution is expected to be a URI in the term url; otherwise, false
45
+ def term_id_expects_uri?
46
+ return false if term_config.nil? || !(term_config.key? :term_id)
47
+ term_config[:term_id] == "URI"
48
+ end
49
+
50
+ # Is the term_id substitution expected to be an ID?
51
+ # @return [True|False] true if the id substitution is expected to be an ID in the term url; otherwise, false
52
+ def term_id_expects_id?
53
+ return false if term_config.nil? || !(term_config.key? :term_id)
54
+ term_config[:term_id] == "ID"
55
+ end
56
+
57
+ # Return the preferred language for literal value selection for term fetch. Only applies if the authority provides language encoded literals.
58
+ # @return [Symbol] the configured language for term fetch (default - :en)
59
+ def term_language
60
+ return @term_language unless @term_language.nil?
61
+ lang = Config.config_value(term_config, :language)
62
+ return nil if lang.nil?
63
+ lang = [lang] if lang.is_a? String
64
+ @term_language = lang.collect(&:to_sym)
65
+ end
66
+
67
+ # Return results predicates
68
+ # @return [Hash] all the configured predicates to pull out of the results
69
+ def term_results
70
+ Config.config_value(term_config, :results)
71
+ end
72
+
73
+ # Return results id_predicate
74
+ # @return [String] the configured predicate to use to extract the id from the results
75
+ def term_results_id_predicate
76
+ Config.predicate_uri(term_results, :id_predicate)
77
+ end
78
+
79
+ # Return results label_predicate
80
+ # @return [String] the configured predicate to use to extract label values from the results
81
+ def term_results_label_predicate
82
+ Config.predicate_uri(term_results, :label_predicate)
83
+ end
84
+
85
+ # Return results altlabel_predicate
86
+ # @return [String] the configured predicate to use to extract altlabel values from the results
87
+ def term_results_altlabel_predicate
88
+ Config.predicate_uri(term_results, :altlabel_predicate)
89
+ end
90
+
91
+ # Return results broader_predicate
92
+ # @return [String] the configured predicate to use to extract URIs for broader terms from the results
93
+ def term_results_broader_predicate
94
+ Config.predicate_uri(term_results, :broader_predicate)
95
+ end
96
+
97
+ # Return results narrower_predicate
98
+ # @return [String] the configured predicate to use to extract URIs for narrower terms from the results
99
+ def term_results_narrower_predicate
100
+ Config.predicate_uri(term_results, :narrower_predicate)
101
+ end
102
+
103
+ # Return results sameas_predicate
104
+ # @return [String] the configured predicate to use to extract URIs for sameas terms from the results
105
+ def term_results_sameas_predicate
106
+ Config.predicate_uri(term_results, :sameas_predicate)
107
+ end
108
+
109
+ # Return parameters that are required for QA api
110
+ # @return [Hash] the configured term url parameter mappings
111
+ def term_qa_replacement_patterns
112
+ Config.config_value(term_config, :qa_replacement_patterns)
113
+ end
114
+
115
+ # Are there replacement parameters configured for term fetch?
116
+ # @return [True|False] true if there are replacement parameters configured for term fetch; otherwise, false
117
+ def term_replacements?
118
+ term_replacement_count.positive?
119
+ end
120
+
121
+ # Return the number of possible replacement values to make in the term URL
122
+ # @return [Integer] the configured number of possible replacements in the term url
123
+ def term_replacement_count
124
+ term_replacements.size
125
+ end
126
+
127
+ # Return the replacement configurations
128
+ # @return [Hash] the configurations for term url replacements
129
+ def term_replacements
130
+ return @term_replacements unless @term_replacements.nil?
131
+ @term_replacements = {}
132
+ @term_replacements = term_url_mappings.select { |k, _v| !term_qa_replacement_patterns.include?(k) } unless term_config.nil? || term_url_mappings.nil?
133
+ @term_replacements
134
+ end
135
+
136
+ # Are there subauthorities configured for term fetch?
137
+ # @return [True|False] true if there are subauthorities configured term fetch; otherwise, false
138
+ def term_subauthorities?
139
+ term_subauthority_count.positive?
140
+ end
141
+
142
+ # Is a specific subauthority configured for term fetch?
143
+ # @return [True|False] true if the specified subauthority is configured for term fetch; otherwise, false
144
+ def term_subauthority?(subauth_name)
145
+ subauth_name = subauth_name.to_sym if subauth_name.is_a? String
146
+ term_subauthorities.key? subauth_name
147
+ end
148
+
149
+ # Return the number of subauthorities defined for term fetch
150
+ # @return [Integer] the number of subauthorities defined for term fetch
151
+ def term_subauthority_count
152
+ term_subauthorities.size
153
+ end
154
+
155
+ # Return the list of subauthorities for term fetch
156
+ # @return [Hash] the configurations for term url replacements
157
+ def term_subauthorities
158
+ @term_subauthorities ||= {} if term_config.nil? || !(term_config.key? :subauthorities)
159
+ @term_subauthorities ||= term_config[:subauthorities]
160
+ end
161
+
162
+ # Return the replacement configurations
163
+ # @return [Hash] the configurations for term url replacements
164
+ def term_subauthority_replacement_pattern
165
+ return {} unless term_subauthorities?
166
+ @term_subauthority_replacement_pattern ||= {} if term_config.nil? || !term_subauthorities?
167
+ pattern = term_qa_replacement_patterns[:subauth]
168
+ @term_subauthority_replacement_pattern ||= { pattern: pattern, default: term_url_mappings[pattern.to_sym][:default] }
169
+ end
170
+
171
+ # Build a linked data authority term url
172
+ # @param [String] the id
173
+ # @param [String] (optional) subauthority key
174
+ # @param [Hash] (optional) replacement values with { pattern_name (defined in YAML config) => value }
175
+ # @return [String] the term encoded url
176
+ def term_url_with_replacements(id, sub_auth = nil, replacements = {})
177
+ return nil unless supports_term?
178
+ sub_auth = sub_auth.to_sym if sub_auth.is_a? String
179
+ url = Config.replace_pattern(term_url_template, term_qa_replacement_patterns[:term_id], id)
180
+ url = Config.process_subauthority(url, term_subauthority_replacement_pattern, term_subauthorities, sub_auth) if term_subauthorities?
181
+ url = Config.apply_replacements(url, term_replacements, replacements) if term_replacements?
182
+ url
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,148 @@
1
+ # This module has the primary QA find method. It also includes methods to process the linked data result and convert
2
+ # it into the expected QA json term result format.
3
+ module Qa::Authorities
4
+ module LinkedData
5
+ class FindTerm
6
+ include Qa::Authorities::LinkedData::RdfHelper
7
+
8
+ # @param [TermConfig] term_config The term portion of the config
9
+ def initialize(term_config)
10
+ @term_config = term_config
11
+ end
12
+
13
+ attr_reader :term_config
14
+
15
+ delegate :term_subauthority?, to: :term_config
16
+
17
+ # Find a single term in a linked data authority
18
+ # @param [String] the id of the term to fetch
19
+ # @param [Symbol] (optional) language: language used to select literals when multi-language is supported (e.g. :en, :fr, etc.)
20
+ # @param [Hash] (optional) replacements: replacement values with { pattern_name (defined in YAML config) => value }
21
+ # @param [String] subauth: the subauthority from which to fetch the term
22
+ # @return [String] json results
23
+ # @example Json Results for Linked Data Term
24
+ # { "uri":"http://id.worldcat.org/fast/530369",
25
+ # "id":"530369","label":"Cornell University",
26
+ # "altlabel":["Ithaca (N.Y.). Cornell University"],
27
+ # "sameas":["http://id.loc.gov/authorities/names/n79021621","https://viaf.org/viaf/126293486"],
28
+ # "predicates":{
29
+ # "http://purl.org/dc/terms/identifier":"530369",
30
+ # "http://www.w3.org/2004/02/skos/core#inScheme":["http://id.worldcat.org/fast/ontology/1.0/#fast","http://id.worldcat.org/fast/ontology/1.0/#facet-Corporate"],
31
+ # "http://www.w3.org/1999/02/22-rdf-syntax-ns#type":"http://schema.org/Organization",
32
+ # "http://www.w3.org/2004/02/skos/core#prefLabel":"Cornell University",
33
+ # "http://schema.org/name":["Cornell University","Ithaca (N.Y.). Cornell University"],
34
+ # "http://www.w3.org/2004/02/skos/core#altLabel":["Ithaca (N.Y.). Cornell University"],
35
+ # "http://schema.org/sameAs":["http://id.loc.gov/authorities/names/n79021621","https://viaf.org/viaf/126293486"] } }
36
+ def find(id, language: nil, replacements: {}, subauth: nil)
37
+ raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data term sub-authority #{subauth}" unless subauth.nil? || term_subauthority?(subauth)
38
+ language ||= term_config.term_language
39
+ url = term_config.term_url_with_replacements(id, subauth, replacements)
40
+ Rails.logger.info "QA Linked Data term url: #{url}"
41
+ graph = get_linked_data(url)
42
+ return "{}" unless graph.size.positive?
43
+ parse_term_authority_response(id, graph, language)
44
+ end
45
+
46
+ private
47
+
48
+ def parse_term_authority_response(id, graph, language)
49
+ graph = filter_language(graph, language) unless language.nil?
50
+ results = extract_preds(graph, preds_for_term)
51
+ consolidated_results = consolidate_term_results(results)
52
+ json_results = convert_term_to_json(consolidated_results)
53
+ termhash = select_json_result_for_id(json_results, id)
54
+ predicates_hash = predicates_with_subject_uri(graph, termhash[:uri])
55
+ termhash['predicates'] = predicates_hash unless predicates_hash.length <= 0
56
+ termhash
57
+ end
58
+
59
+ def preds_for_term
60
+ { required: required_term_preds, optional: optional_term_preds }
61
+ end
62
+
63
+ def required_term_preds
64
+ label_pred_uri = term_config.term_results_label_predicate
65
+ raise Qa::InvalidConfiguration, "required label_predicate is missing in configuration for LOD authority #{auth_name}" if label_pred_uri.nil?
66
+ { label: label_pred_uri }
67
+ end
68
+
69
+ def optional_term_preds
70
+ preds = {}
71
+ preds[:altlabel] = term_config.term_results_altlabel_predicate unless term_config.term_results_altlabel_predicate.nil?
72
+ preds[:id] = term_config.term_results_id_predicate unless term_config.term_results_id_predicate.nil?
73
+ preds[:narrower] = term_config.term_results_narrower_predicate unless term_config.term_results_narrower_predicate.nil?
74
+ preds[:broader] = term_config.term_results_broader_predicate unless term_config.term_results_broader_predicate.nil?
75
+ preds[:sameas] = term_config.term_results_sameas_predicate unless term_config.term_results_sameas_predicate.nil?
76
+ preds
77
+ end
78
+
79
+ def consolidate_term_results(results)
80
+ consolidated_results = {}
81
+ results.each do |statement|
82
+ stmt_hash = statement.to_h
83
+ uri = stmt_hash[:uri].to_s
84
+ consolidated_hash = init_consolidated_hash(consolidated_results, uri, stmt_hash[:id].to_s)
85
+
86
+ consolidated_hash[:label] = object_value(stmt_hash, consolidated_hash, :label, false)
87
+ altlabel = object_value(stmt_hash, consolidated_hash, :altlabel, false)
88
+ narrower = object_value(stmt_hash, consolidated_hash, :narrower)
89
+ broader = object_value(stmt_hash, consolidated_hash, :broader)
90
+ sameas = object_value(stmt_hash, consolidated_hash, :sameas)
91
+
92
+ consolidated_hash[:altlabel] = altlabel unless altlabel.nil?
93
+ consolidated_hash[:narrower] = narrower unless narrower.nil?
94
+ consolidated_hash[:broader] = broader unless broader.nil?
95
+ consolidated_hash[:sameas] = sameas unless sameas.nil?
96
+ consolidated_results[uri] = consolidated_hash
97
+ end
98
+ consolidated_results.each do |res|
99
+ consolidated_hash = res[1]
100
+ consolidated_hash[:label] = sort_string_by_language consolidated_hash[:label]
101
+ consolidated_hash[:altlabel] = sort_string_by_language consolidated_hash[:altlabel]
102
+ consolidated_hash[:sort] = sort_string_by_language consolidated_hash[:sort]
103
+ end
104
+ consolidated_results
105
+ end
106
+
107
+ def convert_term_to_json(consolidated_results)
108
+ json_results = []
109
+ consolidated_results.each do |uri, h|
110
+ json_hash = { uri: uri, id: h[:id], label: h[:label] }
111
+ json_hash[:altlabel] = h[:altlabel] unless h[:altlabel].nil?
112
+ json_hash[:narrower] = h[:narrower] unless h[:narrower].nil?
113
+ json_hash[:broader] = h[:broader] unless h[:broader].nil?
114
+ json_hash[:sameas] = h[:sameas] unless h[:sameas].nil?
115
+ json_results << json_hash
116
+ end
117
+ json_results
118
+ end
119
+
120
+ def select_json_result_for_id(json_results, id)
121
+ json_results.select! { |r| r[:uri].include? id } if json_results.size > 1
122
+ json_results.select! { |r| r[:uri].ends_with? id } if json_results.size > 1
123
+ json_results.first
124
+ end
125
+
126
+ def predicates_with_subject_uri(graph, expected_uri)
127
+ predicates_hash = {}
128
+ graph.statements.each do |st|
129
+ subj = st.subject.to_s
130
+ next unless subj == expected_uri
131
+ pred = st.predicate.to_s
132
+ obj = st.object.to_s
133
+ next if blank_node? obj
134
+ if predicates_hash.key?(pred)
135
+ objs = predicates_hash[pred]
136
+ objs = [] unless objs.is_a?(Array)
137
+ objs << predicates_hash[pred] unless objs.length.positive?
138
+ objs << obj
139
+ predicates_hash[pred] = objs
140
+ else
141
+ predicates_hash[pred] = [obj]
142
+ end
143
+ end
144
+ predicates_hash
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,49 @@
1
+ module Qa::Authorities
2
+ module LinkedData
3
+ # A wrapper around configured linked data authorities for use with questioning_authority. The search and find methods
4
+ # can be called directly from an instance of this class. The Qa::LinkedDataTermsController uses these methods to provide
5
+ # a URL based API for searching and term retrieval.
6
+ #
7
+ # @see Qa::Authorities::LinkedData::SearchQuery#search
8
+ # @see Qa::Authorities::LinkedData::FindTerm#find
9
+ # @see Qa::LinkedDataTermsController#search
10
+ # @see Qa::LinkedDataTermsController#show
11
+ # @see Qa::Authorities::LinkedData::Config
12
+ class GenericAuthority < Base
13
+ attr_reader :auth_config
14
+
15
+ delegate :supports_term?, :term_subauthorities?, :term_subauthority?,
16
+ :term_id_expects_uri?, :term_id_expects_id?, to: :term_config
17
+
18
+ delegate :supports_search?, to: :search_config
19
+ delegate :subauthority?, :subauthorities?, to: :search_config, prefix: 'search'
20
+
21
+ def initialize(auth_name)
22
+ @auth_config = Qa::Authorities::LinkedData::Config.new(auth_name)
23
+ end
24
+
25
+ include WebServiceBase
26
+
27
+ def search_service
28
+ @search_service ||= Qa::Authorities::LinkedData::SearchQuery.new(search_config)
29
+ end
30
+
31
+ def item_service
32
+ @item_service ||= Qa::Authorities::LinkedData::FindTerm.new(term_config)
33
+ end
34
+
35
+ delegate :search, to: :search_service
36
+ delegate :find, to: :item_service
37
+
38
+ private
39
+
40
+ def search_config
41
+ auth_config.search
42
+ end
43
+
44
+ def term_config
45
+ auth_config.term
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,102 @@
1
+ require 'rdf'
2
+
3
+ # Encapsulates processing of RDF results returned by the linked data authority. This is used exclussively by Qa::Authorities::LinkedData::GenericAuthority
4
+ # @see Qa::Authorities::LinkedData::GenericAuthority
5
+ module Qa::Authorities
6
+ module LinkedData
7
+ module RdfHelper
8
+ private
9
+
10
+ def object_value(stmt_hash, consolidated_hash, name, as_string = true)
11
+ new_object_value = stmt_hash[name]
12
+ new_object_value = new_object_value.to_s if as_string
13
+ all_object_values = consolidated_hash[name] || []
14
+ all_object_values << new_object_value unless new_object_value.nil? || all_object_values.include?(new_object_value)
15
+ all_object_values
16
+ end
17
+
18
+ def init_consolidated_hash(consolidated_results, uri, id)
19
+ consolidated_hash = consolidated_results[uri] || {}
20
+ if consolidated_hash.empty?
21
+ consolidated_hash[:id] = uri
22
+ consolidated_hash[:id] = id unless id.nil? || id.length <= 0
23
+ end
24
+ consolidated_hash
25
+ end
26
+
27
+ def get_linked_data(url)
28
+ begin
29
+ graph = RDF::Graph.load(url)
30
+ rescue IOError => e
31
+ process_error(e, url)
32
+ end
33
+ graph
34
+ end
35
+
36
+ def process_error(e, url)
37
+ uri = URI(url)
38
+ response_code = ioerror_code(e)
39
+ case response_code
40
+ when 'format'
41
+ raise RDF::FormatError, "Unknown RDF format of results returned by #{uri}. (RDF::FormatError) You may need to include gem 'linkeddata'."
42
+ when '404'
43
+ raise Qa::TermNotFound, "#{uri} Not Found - Term may not exist at LOD Authority. (HTTPNotFound - 404)"
44
+ when '500'
45
+ raise Qa::ServiceUnavailable, "#{uri.hostname} on port #{uri.port} is not responding. Try again later. (HTTPServerError - 500)"
46
+ when '503'
47
+ raise Qa::ServiceUnavailable, "#{uri.hostname} on port #{uri.port} is not responding. Try again later. (HTTPServiceUnavailable - 503)"
48
+ else
49
+ raise Qa::ServiceUnavailable, "Unknown error for #{uri.hostname} on port #{uri.port}. Try again later. (Cause - #{e.message})"
50
+ end
51
+ end
52
+
53
+ def ioerror_code(e)
54
+ msg = e.message
55
+ return 'format' if msg.start_with? "Unknown RDF format"
56
+ a = msg.size - 4
57
+ z = msg.size - 2
58
+ msg[a..z]
59
+ end
60
+
61
+ def filter_language(graph, language)
62
+ language = normalize_language(language)
63
+ return graph if language.nil?
64
+ graph.each do |st|
65
+ graph.delete(st) unless !st.object.respond_to?(:language) || st.object.language.nil? || language.include?(st.object.language)
66
+ end
67
+ graph
68
+ end
69
+
70
+ def normalize_language(language)
71
+ language = [language.to_sym] if language.is_a? String
72
+ language = [language] if language.is_a? Symbol
73
+ return nil unless language.is_a? Array
74
+ language
75
+ end
76
+
77
+ def extract_preds(graph, preds)
78
+ RDF::Query.execute(graph) do
79
+ preds[:required].each do |key, pred|
80
+ pattern([:uri, pred, key])
81
+ end
82
+ preds[:optional].each do |key, pred|
83
+ pattern([:uri, pred, key], optional: true)
84
+ end
85
+ end
86
+ end
87
+
88
+ def sort_string_by_language(str_literals)
89
+ return str_literals if str_literals.nil? || str_literals.size <= 0
90
+ str_literals.sort! { |a, b| a.language <=> b.language }
91
+ str_literals.collect!(&:to_s)
92
+ str_literals.uniq!
93
+ str_literals.delete_if { |s| s.nil? || s.length <= 0 }
94
+ end
95
+
96
+ def blank_node?(obj)
97
+ return true if obj.to_s.starts_with? "_:g"
98
+ false
99
+ end
100
+ end
101
+ end
102
+ end