lib/earl_report.rb in earl-report-0.5.2 vs lib/earl_report.rb in earl-report-0.5.3

- old
+ new

@@ -150,10 +150,38 @@ } }] }] }.freeze + TURTLE_PREFIXES = %(@prefix dc: <http://purl.org/dc/terms/> . + @prefix doap: <http://usefulinc.com/ns/doap#> . + @prefix earl: <http://www.w3.org/ns/earl#> . + @prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . + @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + @prefix foaf: <http://xmlns.com/foaf/0.1/> . + @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . + @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + ).gsub(/^ /, '') + + TURTLE_SOFTWARE = %( + # Report Generation Software + <https://rubygems.org/gems/earl-report> a earl:Software, doap:Project; + doap:name "earl-report"; + doap:shortdesc "Earl Report summary generator"@en; + doap:description "EarlReport generates HTML+RDFa rollups of multiple EARL reports"@en; + doap:homepage <https://github.com/gkellogg/earl-report>; + doap:programming-language "Ruby"; + doap:license <http://unlicense.org>; + doap:release <https://github.com/gkellogg/earl-report/tree/#{VERSION}>; + doap:developer <https://greggkellogg.net/foaf#me> . + + <https://github.com/gkellogg/earl-report/tree/#{VERSION}> a doap:Version; + doap:name "earl-report-#{VERSION}"; + doap:created "#{File.mtime(File.expand_path('../../VERSION', __FILE__)).strftime('%Y-%m-%d')}"^^xsd:date; + doap:revision "#{VERSION}" . + ).gsub(/^ /, '') + # Convenience vocabularies class EARL < RDF::Vocabulary("http://www.w3.org/ns/earl#"); end class MF < RDF::Vocabulary("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#"); end ## @@ -226,11 +254,10 @@ test_assertion_lists = tests.keys.inject({}) do |memo, test| memo.merge(test => []) end assertion_stats = {} - release_node_mapper = {} # Read test assertion files into assertion graph files.flatten.each do |file| status "read #{file}" file_graph = RDF::Graph.load(file) @@ -378,40 +405,20 @@ end assertion_stats.each {|stat, count| status("Assertions #{stat}: #{count}")} # Add report wrapper to graph - ttl = %( - @prefix dc: <http://purl.org/dc/terms/> . - @prefix doap: <http://usefulinc.com/ns/doap#> . - @prefix earl: <http://www.w3.org/ns/earl#> . - @prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . - @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . - - <> a earl:Software, doap:Project; - doap:name #{quoted(@options.fetch(:name, 'Unknown'))}; - dc:bibliographicCitation "#{@options.fetch(:bibRef, 'Unknown reference')}"; - earl:generatedBy <https://rubygems.org/gems/earl-report>; - earl:assertions #{subjects.values.map {|f| f.to_ntriples}.join(",\n ")}; - earl:testSubjects #{subjects.keys.map {|f| f.to_ntriples}.join(",\n ")}; - mf:entries (#{man_uris.map {|f| f.to_ntriples}.join("\n ")}) . - - <https://rubygems.org/gems/earl-report> a earl:Software, doap:Project; - doap:name "earl-report"; - doap:shortdesc "Earl Report summary generator"@en; - doap:description "EarlReport generates HTML+RDFa rollups of multiple EARL reports"@en; - doap:homepage <https://github.com/gkellogg/earl-report>; - doap:programming-language "Ruby"; - doap:license <http://unlicense.org>; - doap:release <https://github.com/gkellogg/earl-report/tree/#{VERSION}>; - doap:developer <http://greggkellogg.net/foaf#me> . - - <https://github.com/gkellogg/earl-report/tree/#{VERSION}> a doap:Version; - doap:name "earl-report-#{VERSION}"; - doap:created "#{File.mtime(File.expand_path('../../VERSION', __FILE__)).strftime('%Y-%m-%d')}"^^xsd:date; - doap:revision "#{VERSION}" . - ).gsub(/^ /, '') + ttl = TURTLE_PREFIXES + %( + <> a earl:Software, doap:Project; + doap:name #{quoted(@options.fetch(:name, 'Unknown'))}; + dc:bibliographicCitation "#{@options.fetch(:bibRef, 'Unknown reference')}"; + earl:generatedBy <https://rubygems.org/gems/earl-report>; + earl:assertions #{subjects.values.map {|f| f.to_ntriples}.join(",\n ")}; + earl:testSubjects #{subjects.keys.map {|f| f.to_ntriples}.join(",\n ")}; + mf:entries (#{man_uris.map {|f| f.to_ntriples}.join("\n ")}) . + ).gsub(/^ /, '') + + TURTLE_SOFTWARE RDF::Turtle::Reader.new(ttl) {|r| graph << r} # Each manifest is an earl:Report man_uris.each do |u| graph << RDF::Statement.new(u, RDF.type, EARL.Report) @@ -514,53 +521,111 @@ # Output consoloated EARL report as Turtle # @param [Hash{Symbol => Object}] options # @option options [IO, StringIO] :io # @return [String] def earl_turtle(options) + context = JSON::LD::Context.parse(json_hash['@context']) io = options[:io] + io.write(TURTLE_PREFIXES + "\n") - top_level = graph.first_subject(predicate: EARL.generatedBy) + # Write project header + ttl_entity(io, json_hash, context) - # Write starting with the entire graph to get preamble - writer = RDF::Turtle::Writer.new(io, standard_prefixes: true) - writer << graph + # Write out each manifest entry + io.puts("# Manifests") + json_hash['entries'].each do |man| + ttl_entity(io, man, context) - writer.send(:preprocess) - writer.send(:start_document) + # Output each test entry with assertions + man['entries'].each do |entry| + ttl_entity(io, entry, context) + end + end - # Write top-level object referencing manifests and subjects - writer.send(:statement, top_level) + # Output each DOAP + json_hash['testSubjects'].each do |doap| + ttl_entity(io, doap, context) - # Write each manifest - io.puts "\n# Manifests" - RDF::List.new(subject: graph.first_object(subject: top_level, predicate: MF[:entries]), graph: graph).each do |manifest| - writer.send(:statement, manifest) - - # Write each test case - RDF::List.new(subject: graph.first_object(subject: manifest, predicate: MF[:entries]), graph: graph).each do |tc| - writer.send(:statement, tc) + # FOAF + dev = doap['developer'] + dev = [dev] unless dev.is_a?(Array) + dev.each do |foaf| + ttl_entity(io, foaf, context) end end + + io.write(TURTLE_SOFTWARE) + end - # Write test subjects - io.puts "\n# Test Subjects" - graph.query({subject: top_level, predicate: EARL.testSubjects}).each do |s| - writer.send(:statement, s.object) + def ttl_entity(io, entity, context) + io.write(ttl_value(entity) + " " + entity.map do |dk, dv| + case dk + when '@context', '@id' + nil + when '@type' + "a " + ttl_value(dv) + when 'assertions' + "earl:assertions #{dv.map {|a| ttl_assertion(a)}.join(", ")}" + when 'entries' + "mf:entries #{ttl_value({'@list' => dv}, whitespace: "\n ")}" + when 'release' + "doap:release [doap:revision #{quoted(dv['revision'])}]" + else + dv = [dv] unless dv.is_a?(Array) + dv = dv.map {|v| v.is_a?(Hash) ? v : context.expand_value(dk, v)} + "#{ttl_value(dk)} #{ttl_value(dv, whitespace: "\n ")}" + end + end.compact.join(" ;\n ") + " .\n\n") + end - # Write each developer - graph.query({subject: s.object, predicate: RDF::Vocab::DOAP.developer}).each do |d| - writer.send(:statement, d.object) + def ttl_value(value, whitespace: " ") + if value.is_a?(Array) + value.map {|v| ttl_value(v)}.join(",#{whitespace}") + elsif value.is_a?(Hash) + if value.key?('@list') + "(#{value['@list'].map {|vv| ttl_value(vv)}.join(whitespace)})" + elsif value.key?('@value') + quoted(value['@value'], language: value['@language'], datatype: value['@type']) + elsif value.key?('@id') + ttl_value(value['@id']) + else + "[]" end + elsif value.start_with?(/https?/) || value.start_with?('/') + "<#{value}>" + elsif value.include?(':') + value + elsif json_hash['@context'][value].is_a?(Hash) + json_hash['@context'][value].fetch('@id', "earl:#{value}") + elsif value.empty? + "<>" + else + "earl:#{value}" end + end - # Write generator - io.puts "\n# Report Generation Software" - writer.send(:statement, RDF::URI("https://rubygems.org/gems/earl-report")) - writer.send(:statement, RDF::URI("https://github.com/gkellogg/earl-report/tree/#{VERSION}")) + def ttl_assertion(value) + return ttl_value(value) if value.is_a?(String) + block = [ + "[", + " a earl:Assertion ;", + " earl:test #{ttl_value(value['test'])} ;", + " earl:subject #{ttl_value(value['subject'])} ;", + " earl:result [", + " a earl:TestResult ;", + " earl:outcome #{ttl_value(value['result']['outcome'])}", + " ] ;", + ] + block << " earl:assertedBy #{ttl_value(value['assertedBy'])} ;" if value['assertedBy'] + + block.join("\n") + "\n ]" end - def quoted(string) - (@turtle_writer ||= RDF::Turtle::Writer.new).send(:quoted, string) + def quoted(string, language: nil, datatype: nil) + str = (@turtle_writer ||= RDF::Turtle::Writer.new).send(:quoted, string) + str += "@#{language}" if language + str += "^^#{ttl_value(datatype)}" if datatype + str end def warn(message) $stderr.puts message end