|
| 1 | +#!/usr/bin/env ruby |
| 2 | +require 'rubygems' |
| 3 | +$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib'))) |
| 4 | +begin |
| 5 | + require 'linkeddata' |
| 6 | +rescue LoadError |
| 7 | +end |
| 8 | +require 'json/ld' |
| 9 | +require 'getoptlong' |
| 10 | +require 'open-uri' |
| 11 | + |
| 12 | +def run(input, options) |
| 13 | + reader_class = RDF::Reader.for(options[:input_format].to_sym) |
| 14 | + raise "Reader not found for #{options[:input_format]}" unless reader_class |
| 15 | + |
| 16 | + # Override default (or specified) output format when framing |
| 17 | + options[:format] = :jsonld if options[:compact] || options[:frame] |
| 18 | + |
| 19 | + # If input format is not JSON-LD, transform input to JSON-LD first |
| 20 | + if options[:format] == :jsonld && options[:input_format] != :jsonld |
| 21 | + r = reader_class.new(input, options[:parser_options]) |
| 22 | + g = RDF::Repository.new << r |
| 23 | + input = JSON::LD::API.fromRDF(g) |
| 24 | + end |
| 25 | + |
| 26 | + prefixes = {} |
| 27 | + start = Time.new |
| 28 | + if options[:expand] |
| 29 | + output = JSON::LD::API.expand(input, options[:context], nil, options) |
| 30 | + secs = Time.new - start |
| 31 | + options[:output].puts output.to_json(JSON::LD::JSON_STATE) |
| 32 | + STDERR.puts "Expanded in #{secs} seconds." unless options[:quiet] |
| 33 | + elsif options[:compact] |
| 34 | + output = JSON::LD::API.compact(input, options[:context], nil, options) |
| 35 | + secs = Time.new - start |
| 36 | + options[:output].puts output.to_json(JSON::LD::JSON_STATE) |
| 37 | + STDERR.puts "Compacted in #{secs} seconds." unless options[:quiet] |
| 38 | + elsif options[:frame] |
| 39 | + output = JSON::LD::API.frame(input, options[:frame], nil, options) |
| 40 | + secs = Time.new - start |
| 41 | + options[:output].puts output.to_json(JSON::LD::JSON_STATE) |
| 42 | + STDERR.puts "Framed in #{secs} seconds." unless options[:quiet] |
| 43 | + else |
| 44 | + r = reader_class.new(input, options[:parser_options]) |
| 45 | + g = RDF::Repository.new << r |
| 46 | + secs = Time.new - start |
| 47 | + num = g.count |
| 48 | + parser_options = options[:parser_options].merge(:prefixes => r.prefixes, :standard_prefixes => true) |
| 49 | + options[:output].puts g.dump(options[:output_format], parser_options) |
| 50 | + STDERR.puts "\nParsed #{num} statements in #{secs} seconds @ #{num/secs} statements/second." unless options[:quiet] |
| 51 | + end |
| 52 | +rescue |
| 53 | + fname = input.respond_to?(:path) ? input.path : "-stdin-" |
| 54 | + STDERR.puts("Error in #{fname}") |
| 55 | + raise |
| 56 | +end |
| 57 | + |
| 58 | +parser_options = { |
| 59 | + :base => "", |
| 60 | + :progress => false, |
| 61 | + :validate => false, |
| 62 | + :strict => false, |
| 63 | +} |
| 64 | + |
| 65 | +options = { |
| 66 | + :parser_options => parser_options, |
| 67 | + :output => STDOUT, |
| 68 | + :output_format => :turtle, |
| 69 | + :input_format => :jsonld, |
| 70 | +} |
| 71 | +input = nil |
| 72 | + |
| 73 | +OPT_ARGS = [ |
| 74 | + ["--dbg", GetoptLong::NO_ARGUMENT, "Turn on verbose debugging"], |
| 75 | + ["--compact", GetoptLong::NO_ARGUMENT, "Compact document, using --context"], |
| 76 | + ["--context", GetoptLong::REQUIRED_ARGUMENT,"Context to apply for expand, compact and converting from RDF"], |
| 77 | + ["--evaluate","-e", GetoptLong::REQUIRED_ARGUMENT,"Evaluate argument as a JSON-LD document"], |
| 78 | + ["--expand", GetoptLong::NO_ARGUMENT, "Expand document, using an optional --context"], |
| 79 | + ["--format", GetoptLong::REQUIRED_ARGUMENT,"Specify output format when converting to RDF"], |
| 80 | + ["--frame", GetoptLong::REQUIRED_ARGUMENT,"Frame document, using the file or URL as a frame specification"], |
| 81 | + ["--input-format", GetoptLong::REQUIRED_ARGUMENT,"Format of the input document, when converting from RDF."], |
| 82 | + ["--output", "-o", GetoptLong::REQUIRED_ARGUMENT,"Output to the specified file path"], |
| 83 | + ["--parse-only", GetoptLong::NO_ARGUMENT, "Parse the document for well-formedness only"], |
| 84 | + ["--quiet", GetoptLong::NO_ARGUMENT, "Supress most output other than progress indicators"], |
| 85 | + ["--uri", GetoptLong::REQUIRED_ARGUMENT,"URI to be used as the document base"], |
| 86 | + ["--verbose", GetoptLong::NO_ARGUMENT, "Detail on execution"], |
| 87 | + ["--help", "-?", GetoptLong::NO_ARGUMENT, "This message"] |
| 88 | +] |
| 89 | +def usage |
| 90 | + STDERR.puts %{Usage: #{$0} [options] file ...} |
| 91 | + width = OPT_ARGS.map do |o| |
| 92 | + l = o.first.length |
| 93 | + l += o[1].length + 2 if o[1].is_a?(String) |
| 94 | + l |
| 95 | + end.max |
| 96 | + OPT_ARGS.each do |o| |
| 97 | + s = " %-*s " % [width, (o[1].is_a?(String) ? "#{o[0,2].join(', ')}" : o[0])] |
| 98 | + s += o.last |
| 99 | + STDERR.puts s |
| 100 | + end |
| 101 | + exit(1) |
| 102 | +end |
| 103 | + |
| 104 | + |
| 105 | +opts = GetoptLong.new(*OPT_ARGS.map {|o| o[0..-2]}) |
| 106 | + |
| 107 | +opts.each do |opt, arg| |
| 108 | + case opt |
| 109 | + when '--dbg' then parser_options[:debug] = ::JSON::LD::debug = true |
| 110 | + when '--compact' then options[:compact] = true |
| 111 | + when '--context' then options[:context] = arg |
| 112 | + when '--execute' then input = arg |
| 113 | + when '--expand' then options[:expand] = true |
| 114 | + when '--format' then options[:output_format] = arg.to_sym |
| 115 | + when '--frame' then options[:frame] = arg |
| 116 | + when '--input-format' then options[:input_format] = arg.to_sym |
| 117 | + when '--output' then options[:output] = File.open(arg, "w") |
| 118 | + when '--parse-only' then options[:parse_only] = true |
| 119 | + when '--quiet' then options[:quiet] = true |
| 120 | + when '--uri' then parser_options[:base] = arg |
| 121 | + when '--verbose' then $verbose = true |
| 122 | + when '--help' then usage |
| 123 | + end |
| 124 | +end |
| 125 | + |
| 126 | +if ARGV.empty? |
| 127 | + s = input ? input : $stdin.read |
| 128 | + run(StringIO.new(s), options) |
| 129 | +else |
| 130 | + ARGV.each do |file| |
| 131 | + run(Kernel.open(file), options) |
| 132 | + end |
| 133 | +end |
| 134 | +puts |
0 commit comments