Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extract out ldpath processing into ldpath service
- Loading branch information
Showing
9 changed files
with
147 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Defines the external authority predicates used to extract additional context from the graph. | ||
require 'ldpath' | ||
|
||
module Qa | ||
module LinkedData | ||
class LdpathService | ||
VALUE_ON_ERROR = [].freeze | ||
|
||
# Create the ldpath program for a given ldpath. | ||
# @param ldpath [String] ldpath to follow to get a value from a graph (documation: http://marmotta.apache.org/ldpath/language.html) | ||
# @param prefixes [Hash] shortcut names for URI prefixes with key = part of predicate that is the same for all terms (e.g. { "madsrdf": "http://www.loc.gov/mads/rdf/v1#" }) | ||
# @return [Ldpath::Program] an executable program that will extract a value from a graph | ||
def self.ldpath_program(ldpath:, prefixes: {}) | ||
program_code = "" | ||
prefixes.each { |key, url| program_code << "@prefix #{key} : <#{url}> \;\n" } | ||
program_code << "property = #{ldpath} \;" | ||
Ldpath::Program.parse program_code | ||
rescue => e | ||
Rails.logger.warn("WARNING: #{I18n.t('qa.linked_data.ldpath.parse_logger_error')}... cause: #{e.message}\n ldpath_program=\n#{program_code}") | ||
raise StandardError, I18n.t("qa.linked_data.ldpath.parse_error") + "... cause: #{e.message}" | ||
end | ||
|
||
# Evaluate an ldpath for a specific subject uri in the context of a graph and return the extracted values. | ||
# @param program [Ldpath::Program] an executable program that will extract a value from a graph | ||
# @param graph [RDF::Graph] the graph from which the values will be extracted | ||
# @param subject_uri [RDF::URI] retrieved values will be limited to those with the subject uri | ||
# @param limit_to_context [Boolean] if true, the evaluation process will not make any outside network calls. | ||
# It will limit results to those found in the context graph. | ||
## @return [Array<String>] the extracted values based on the ldpath | ||
def self.ldpath_evaluate(program:, graph:, subject_uri:, limit_to_context: Qa.config.limit_ldpath_to_context?) | ||
return VALUE_ON_ERROR if program.blank? | ||
output = program.evaluate(subject_uri, context: graph, limit_to_context: limit_to_context) | ||
output.present? ? output['property'].uniq : nil | ||
rescue => e | ||
Rails.logger.warn("WARNING: #{I18n.t('qa.linked_data.ldpath.evaluate_logger_error')} (cause: #{e.message}") | ||
raise StandardError, I18n.t("qa.linked_data.ldpath.evaluate_error") + "... cause: #{e.message}" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe Qa::LinkedData::LdpathService do | ||
let(:ldpath) { 'skos:prefLabel ::xsd:string' } | ||
|
||
describe '.ldpath_program' do | ||
subject { described_class.ldpath_program(ldpath: ldpath, prefixes: prefixes) } | ||
|
||
let(:prefixes) do | ||
{ skos: 'http://www.w3.org/2004/02/skos/core#' } | ||
end | ||
|
||
it 'returns instance of Ldpath::Program' do | ||
expect(subject).to be_kind_of Ldpath::Program | ||
end | ||
|
||
context 'when ldpath_program gets parse error' do | ||
let(:cause) { "undefined method `ascii_tree' for nil:NilClass" } | ||
let(:warning) { I18n.t('qa.linked_data.ldpath.parse_logger_error') } | ||
let(:program_code) { "@prefix skos : <http://www.w3.org/2004/02/skos/core#> ;\nproperty = skos:prefLabel ::xsd:string ;" } | ||
let(:log_message) { "WARNING: #{warning}... cause: #{cause}\n ldpath_program=\n#{program_code}" } | ||
|
||
before { allow(Ldpath::Program).to receive(:parse).with(anything).and_raise(cause) } | ||
|
||
it 'logs error and returns PARSE ERROR as the value' do | ||
expect(Rails.logger).to receive(:warn).with(log_message) | ||
expect { subject.values(graph, subject_uri) }.to raise_error StandardError, I18n.t('qa.linked_data.ldpath.parse_error') + "... cause: #{cause}" | ||
end | ||
end | ||
end | ||
|
||
describe '.ldpath_evaluate' do | ||
subject { described_class.ldpath_evaluate(program: program, graph: graph, subject_uri: subject_uri) } | ||
|
||
let(:program) { instance_double(Ldpath::Program) } | ||
let(:graph) { instance_double(RDF::Graph) } | ||
let(:subject_uri) { instance_double(RDF::URI) } | ||
let(:values) { ['Expanded Label'] } | ||
|
||
before do | ||
allow(Ldpath::Program).to receive(:parse).with('property = skos:prefLabel ::xsd:string ;').and_return(program) | ||
allow(program).to receive(:evaluate).with(subject_uri, context: graph, limit_to_context: true).and_return('property' => values) | ||
end | ||
it 'returns the extracted label' do | ||
expect(subject).to match_array values | ||
end | ||
|
||
context 'when ldpath_evaluate gets parse error' do | ||
let(:cause) { "unknown cause" } | ||
let(:warning) { I18n.t('qa.linked_data.ldpath.evaluate_logger_error') } | ||
let(:log_message) { "WARNING: #{warning} (cause: #{cause}" } | ||
|
||
before { allow(program).to receive(:evaluate).with(subject_uri, context: graph, limit_to_context: true).and_raise(cause) } | ||
|
||
it 'logs error and returns PARSE ERROR as the value' do | ||
expect(Rails.logger).to receive(:warn).with(log_message) | ||
expect { subject.values(graph, subject_uri) }.to raise_error StandardError, I18n.t('qa.linked_data.ldpath.evaluate_error') + "... cause: #{cause}" | ||
end | ||
end | ||
end | ||
end |