ftr_ruby 0.1.4

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.
data/lib/output.rb ADDED
@@ -0,0 +1,181 @@
1
+ module FtrRuby
2
+ ##
3
+ # Represents the output/result of executing a FAIR test against a specific resource.
4
+ #
5
+ # This class generates a provenance-rich RDF graph describing a single test execution,
6
+ # including the result score, log messages, summary, and optional guidance for improvement.
7
+ #
8
+ # The output follows the FAIR Test Registry (FTR) vocabulary and uses PROV for tracing
9
+ # the execution activity and the tested entity.
10
+ #
11
+ # @example
12
+ # output = FtrRuby::Output.new(
13
+ # testedGUID: "https://doi.org/10.5281/zenodo.1234567",
14
+ # meta: test_meta_hash
15
+ # )
16
+ # output.score = "pass"
17
+ # output.comments << "Resource has a resolvable persistent identifier."
18
+ # jsonld = output.createEvaluationResponse
19
+ #
20
+ class Output
21
+ include TripleEasy # get the :"triplify" function
22
+ # triplify(s, p, o, repo, datatype: nil, context: nil, language: 'en')
23
+ include RDF
24
+
25
+ attr_accessor :score, :testedGUID, :testid, :uniqueid, :name, :description, :license, :dt, :metric, :softwareid,
26
+ :version, :summary, :completeness, :comments, :guidance, :creator, :protocol, :host, :basePath, :api
27
+
28
+ OPUTPUT_VERSION = "1.1.1"
29
+
30
+ ##
31
+ # Creates a new test output instance.
32
+ #
33
+ # @param testedGUID [String] The identifier (usually URI) of the resource being tested
34
+ # @param meta [Hash] Metadata about the test (same structure used by DCAT_Record)
35
+ #
36
+ def initialize(testedGUID:, meta:)
37
+ @score = "indeterminate"
38
+ @testedGUID = testedGUID
39
+ @uniqueid = "urn:fairtestoutput:" + SecureRandom.uuid
40
+ @name = meta[:testname]
41
+ @description = meta[:description]
42
+ @license = meta[:license] || "https://creativecommons.org/licenses/by/4.0/"
43
+ @dt = Time.now.iso8601
44
+ @metric = meta[:metric]
45
+ @version = meta[:testversion]
46
+ @summary = meta[:summary] || "Summary:"
47
+ @completeness = "100"
48
+ @comments = []
49
+ @guidance = meta.fetch(:guidance, [])
50
+ @creator = meta[:creator]
51
+ @protocol = meta[:protocol].gsub(%r{[:/]}, "")
52
+ @host = meta[:host].gsub(%r{[:/]}, "")
53
+ @basePath = meta[:basePath].gsub(%r{[:/]}, "")
54
+ @softwareid = "#{@protocol}://#{@host}/#{@basePath}/#{meta[:testid]}"
55
+ @api = "#{@softwareid}/api"
56
+ end
57
+
58
+ ##
59
+ # Generates the full evaluation response as JSON-LD.
60
+ #
61
+ # Builds an RDF graph containing:
62
+ # * A `ftr:TestExecutionActivity`
63
+ # * A `ftr:TestResult` with score, summary, log, and guidance
64
+ # * Links to the tested entity and the test software
65
+ # * Provenance information
66
+ #
67
+ # @return [String] JSON-LD representation of the test result graph
68
+ #
69
+ def createEvaluationResponse
70
+ g = RDF::Graph.new
71
+ schema = RDF::Vocab::SCHEMA
72
+ xsd = RDF::Vocab::XSD
73
+ dct = RDF::Vocab::DC
74
+ prov = RDF::Vocab::PROV
75
+ dcat = RDF::Vocab::DCAT
76
+ dqv = RDF::Vocabulary.new("https://www.w3.org/TR/vocab-dqv/")
77
+ ftr = RDF::Vocabulary.new("https://w3id.org/ftr#")
78
+ sio = RDF::Vocabulary.new("http://semanticscience.org/resource/")
79
+ cwmo = RDF::Vocabulary.new("http://purl.org/cwmo/#")
80
+
81
+ add_newline_to_comments
82
+
83
+ if summary =~ /^Summary$/
84
+ summary = "Summary of test results: #{comments[-1]}"
85
+ summary ||= "Summary of test results: #{comments[-2]}"
86
+ end
87
+
88
+ executionid = "urn:ostrails:testexecutionactivity:" + SecureRandom.uuid
89
+
90
+ # tid = 'urn:ostrails:fairtestentity:' + SecureRandom.uuid
91
+ # The entity is no longer an anonymous node, it is the GUID Of the tested input
92
+
93
+ triplify(executionid, RDF.type, ftr.TestExecutionActivity, g)
94
+ triplify(executionid, prov.wasAssociatedWith, softwareid, g)
95
+ triplify(uniqueid, prov.wasGeneratedBy, executionid, g)
96
+
97
+ triplify(uniqueid, RDF.type, ftr.TestResult, g)
98
+ triplify(uniqueid, dct.identifier, uniqueid.to_s, g, datatype: xsd.string)
99
+ triplify(uniqueid, dct.title, "#{name} OUTPUT", g)
100
+ triplify(uniqueid, dct.description, "OUTPUT OF #{description}", g)
101
+ triplify(uniqueid, dct.license, license, g)
102
+ triplify(uniqueid, prov.value, score, g)
103
+ triplify(uniqueid, ftr.summary, summary, g)
104
+ triplify(uniqueid, RDF::Vocab::PROV.generatedAtTime, dt, g)
105
+ triplify(uniqueid, ftr.log, comments.join, g)
106
+ triplify(uniqueid, ftr.completion, completeness, g)
107
+
108
+ triplify(uniqueid, ftr.outputFromTest, softwareid, g)
109
+ triplify(softwareid, RDF.type, ftr.Test, g)
110
+ triplify(softwareid, RDF.type, schema.SoftwareApplication, g)
111
+ triplify(softwareid, RDF.type, dcat.DataService, g)
112
+ triplify(softwareid, dct.identifier, softwareid.to_s, g, datatype: xsd.string)
113
+ triplify(softwareid, dct.title, "#{name}", g)
114
+ triplify(softwareid, dct.description, description, g)
115
+ triplify(softwareid, dcat.endpointDescription, api, g) # returns yaml
116
+ triplify(softwareid, dcat.endpointURL, softwareid, g) # POST to execute
117
+ triplify(softwareid, "http://www.w3.org/ns/dcat#version", "#{version} OutputVersion:#{OPUTPUT_VERSION}", g) # dcat namespace in library has no version - dcat 2 not 3
118
+ triplify(softwareid, dct.license, "https://github.com/wilkinsonlab/FAIR-Core-Tests/blob/main/LICENSE", g)
119
+ triplify(softwareid, sio["SIO_000233"], metric, g) # implementation of
120
+
121
+ # deprecated after release 1.0
122
+ # triplify(uniqueid, prov.wasDerivedFrom, tid, g)
123
+ # triplify(executionid, prov.used, tid, g)
124
+ # triplify(tid, RDF.type, prov.Entity, g)
125
+ # triplify(tid, schema.identifier, testedGUID, g, xsd.string)
126
+ # triplify(tid, schema.url, testedGUID, g) if testedGUID =~ %r{^https?://}
127
+ testedguidnode = "urn:ostrails:testedidentifiernode:" + SecureRandom.uuid
128
+
129
+ begin
130
+ triplify(uniqueid, ftr.assessmentTarget, testedguidnode, g)
131
+ triplify(executionid, prov.used, testedguidnode, g)
132
+ triplify(testedguidnode, RDF.type, prov.Entity, g)
133
+ triplify(testedguidnode, dct.identifier, testedGUID, g, datatype: xsd.string)
134
+ rescue StandardError
135
+ triplify(uniqueid, ftr.assessmentTarget, "not a URI", g)
136
+ triplify(executionid, prov.used, "not a URI", g)
137
+ score = "fail"
138
+ end
139
+
140
+ unless score == "pass"
141
+ guidance.each do |advice, label|
142
+ adviceid = "urn:ostrails:testexecutionactivity:advice:" + SecureRandom.uuid
143
+ triplify(uniqueid, ftr.suggestion, adviceid, g)
144
+ triplify(adviceid, RDF.type, ftr.GuidanceContext, g)
145
+ triplify(adviceid, RDFS.label, label, g)
146
+ triplify(adviceid, dct.description, label, g)
147
+ triplify(adviceid, sio["SIO_000339"], RDF::URI.new(advice), g)
148
+ end
149
+ end
150
+
151
+ # g.dump(:jsonld)
152
+ w = RDF::Writer.for(:jsonld)
153
+ w.dump(g, nil, prefixes: {
154
+ xsd: RDF::Vocab::XSD,
155
+ prov: RDF::Vocab::PROV,
156
+ dct: RDF::Vocab::DC,
157
+ dcat: RDF::Vocab::DCAT,
158
+ ftr: ftr,
159
+ sio: sio,
160
+ schema: schema
161
+ })
162
+ end
163
+
164
+ class << self
165
+ attr_reader :comments
166
+ end
167
+
168
+ def self.clear_comments
169
+ @comments = []
170
+ end
171
+
172
+ def add_newline_to_comments
173
+ cleancomments = []
174
+ @comments.each do |c|
175
+ c += "\n" unless c =~ /\n$/
176
+ cleancomments << c
177
+ end
178
+ @comments = cleancomments
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,23 @@
1
+ require "rest-client"
2
+ module FtrRuby
3
+ class Tests
4
+ def self.register_test(test_uri:, proxy_url: "https://tools.ostrails.eu/fdp-index-proxy/proxy")
5
+ warn "registering new test"
6
+ # curl -v -L -H "content-type: application/json"
7
+ # -d '{"clientUrl": "https://my.domain.org/path/to/DCAT/testdcat.ttl"}'
8
+ # https://tools.ostrails.eu/fdp-index-proxy/proxy
9
+ begin
10
+ response = RestClient::Request.execute({
11
+ method: :post,
12
+ url: proxy_url,
13
+ headers: { "Accept" => "application/json",
14
+ "Content-Type" => "application/json" },
15
+ payload: { "clientUrl": test_uri }.to_json
16
+ }).body
17
+ rescue StandardError => e
18
+ warn "response is #{response.inspect} error #{e.inspect}"
19
+ end
20
+ response
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,53 @@
1
+ module FtrRuby
2
+ class TestInfra
3
+ attr_accessor :test_protocol, :test_host, :basepath
4
+
5
+ def initialize(test_host:, basepath:, test_protocol:)
6
+ @test_host = test_host
7
+ @test_protocol = test_protocol
8
+ @basepath = basepath
9
+ end
10
+
11
+ # there is a need to map between a test and its registered Metric in FS. This will return the label for the test
12
+ # in principle, we cojuld return a more complex object, but all I need now is the label
13
+ def get_tests_metrics(tests:)
14
+ labels = {}
15
+ landingpages = {}
16
+ tests.each do |testid|
17
+ warn "getting dcat for #{testid} #{test_protocol}://#{test_host}/#{basepath}/#{testid}"
18
+ dcat = RestClient::Request.execute({
19
+ method: :get,
20
+ url: "#{test_protocol}://#{test_host}/#{basepath}/#{testid}",
21
+ headers: { "Accept" => "application/json" }
22
+ }).body
23
+ parseddcat = JSON.parse(dcat)
24
+ # this next line should probably be done with SPARQL
25
+ # # TODO TODO TODO
26
+ jpath = JsonPath.new('[0]["http://semanticscience.org/resource/SIO_000233"][0]["@id"]') # is implementation of
27
+ metricurl = jpath.on(parseddcat).first
28
+
29
+ begin
30
+ g = RDF::Graph.load(metricurl, format: :turtle)
31
+ rescue StandardError => e
32
+ warn "DCAT Metric loading failed #{e.inspect}"
33
+ g = RDF::Graph.new
34
+ end
35
+
36
+ title = g.query([nil, RDF::Vocab::DC.title, nil])&.first&.object&.to_s
37
+ lp = g.query([nil, RDF::Vocab::DCAT.landingPage, nil])&.first&.object&.to_s
38
+
39
+ labels[testid] = if title != ""
40
+ title
41
+ else
42
+ "Metric label not available"
43
+ end
44
+ landingpages[testid] = if lp != ""
45
+ lp
46
+ else
47
+ ""
48
+ end
49
+ end
50
+ [labels, landingpages]
51
+ end
52
+ end
53
+ end
data/sig/ftr_ruby.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module FtrRuby
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ftr_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - markwilkinson
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Libraries supporting the FAIR Testing Resources Vocabulary - Tests and
13
+ test outputs.
14
+ email:
15
+ - mark.wilkinson@upm.es
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - LICENSE.txt
22
+ - Rakefile
23
+ - doc/CHANGELOG_md.html
24
+ - doc/FtrRuby.html
25
+ - doc/FtrRuby/DCAT_Record.html
26
+ - doc/FtrRuby/Error.html
27
+ - doc/FtrRuby/FDPIndex.html
28
+ - doc/FtrRuby/Output.html
29
+ - doc/FtrRuby/TestInfra.html
30
+ - doc/FtrRuby/Tests.html
31
+ - doc/Gemfile.html
32
+ - doc/Gemfile_lock.html
33
+ - doc/LICENSE_txt.html
34
+ - doc/OpenAPI.html
35
+ - doc/README_md.html
36
+ - doc/Rakefile.html
37
+ - doc/bin/setup.html
38
+ - doc/created.rid
39
+ - doc/css/rdoc.css
40
+ - doc/index.html
41
+ - doc/js/aliki.js
42
+ - doc/js/bash_highlighter.js
43
+ - doc/js/c_highlighter.js
44
+ - doc/js/search_controller.js
45
+ - doc/js/search_data.js
46
+ - doc/js/search_navigation.js
47
+ - doc/js/search_ranker.js
48
+ - doc/js/theme-toggle.js
49
+ - doc/sig/ftr_ruby_rbs.html
50
+ - lib/dcat_metadata.rb
51
+ - lib/fdp_index.rb
52
+ - lib/ftr_ruby.rb
53
+ - lib/ftr_ruby/version.rb
54
+ - lib/openapi.rb
55
+ - lib/output.rb
56
+ - lib/registertest.rb
57
+ - lib/test_infrastructure.rb
58
+ - sig/ftr_ruby.rbs
59
+ homepage: https://github.com/markwilkinson/FTR-Ruby/tree/master
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ allowed_push_host: https://rubygems.org
64
+ homepage_uri: https://github.com/markwilkinson/FTR-Ruby/tree/master
65
+ source_code_uri: https://github.com/markwilkinson/FTR-Ruby/tree/master
66
+ documentation_uri: https://rubydoc.info/gems/ftr_ruby
67
+ bug_tracker_uri: https://github.com/markwilkinson/FTR-Ruby/issues
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 4.0.9
83
+ specification_version: 4
84
+ summary: Libraries supporting the FTR Vocabulary.
85
+ test_files: []