0
|
1 #!/usr/bin/env ruby
|
|
2 $: << File.expand_path('../rubylib/lib', File.dirname(__FILE__))
|
|
3 $: << File.expand_path('sparql/lib', File.dirname(__FILE__))
|
|
4 require "galaxy_tool"
|
|
5 require 'rubygems'
|
|
6 require 'sparql'
|
|
7 require 'rubyrdf'
|
|
8
|
|
9 class SPARQLExecutor < GalaxyTool::Base
|
|
10
|
|
11 option :endpoint,
|
|
12 :short => "-e",
|
|
13 :long => "--endpoint <URL>",
|
|
14 :class => String,
|
|
15 :description => "use <URL> as SPARQL endpoint.",
|
|
16 :proc => proc {|arg| arg.strip },
|
|
17 :required => true
|
|
18
|
|
19 option :query,
|
|
20 :long => "--query-file <filepath>",
|
|
21 :class => String,
|
|
22 :description => "read query expression from <filepath>.",
|
|
23 :proc => proc {|arg| File.read(arg).chomp },
|
|
24 :required => true
|
|
25
|
|
26 option :query,
|
|
27 :short => "-q",
|
|
28 :long => "--query <expression>",
|
|
29 :class => String,
|
|
30 :description => "use <expression> as query expression.",
|
|
31 :proc => proc {|arg| arg.chomp },
|
|
32 :required => true
|
|
33
|
|
34 option_output :short => "-o",
|
|
35 :long => "--output <filepath>",
|
|
36 :description => "use <filepath> as output file path."
|
|
37
|
|
38 option_info :long => "--info <filepath>",
|
|
39 :description => "use <filepath> as info file path. default is standard out (/dev/stdout)."
|
|
40
|
|
41 option_error_handler do |optparse, exception|
|
|
42 $stderr.puts "Error: " + exception.message
|
|
43 $stderr.puts optparse.help
|
|
44 raise exception
|
|
45 end
|
|
46
|
|
47 def info(info_out)
|
|
48 info_out.puts "Execute SPARQL query. The endpoint is #{options[:endpoint]}.\n"
|
|
49 end
|
|
50
|
|
51 def create_customized_client(endpoint)
|
|
52 client = SPARQL::Client.new(endpoint)
|
|
53
|
|
54 def client.parsed_xml(content)
|
|
55 REXML::Document.new(content).root
|
|
56 end
|
|
57
|
|
58 def client.parse_xml(content)
|
|
59 table = []
|
|
60 xml = parsed_xml(content)
|
|
61
|
|
62 head = xml.elements['head']
|
|
63 variables = head.elements.map do |variable|
|
|
64 variable.attributes['name']
|
|
65 end
|
|
66 table << variables.map {|v| "?" + v }
|
|
67
|
|
68 case
|
|
69 when boolean = xml.elements['boolean']
|
|
70 boolean.text == 'true'
|
|
71 when results = xml.elements['results']
|
|
72 table += results.elements.map do |result|
|
|
73 row = []
|
|
74 result.elements.each do |binding|
|
|
75 name = binding.attributes['name']
|
|
76 value_node = binding.children.find {|n| !n.is_a?(REXML::Text) }
|
|
77 value = parse_xml_value(value_node)
|
|
78 row[variables.index(name)] = value
|
|
79 end
|
|
80 row
|
|
81 end
|
|
82 else
|
|
83 raise NotImplementedError # TODO
|
|
84 end
|
|
85
|
|
86 table
|
|
87 end
|
|
88
|
|
89 def client.graph
|
|
90 @graph ||= RDF::Graph::Memory.new
|
|
91 end
|
|
92
|
|
93 def client.parse_xml_value(element)
|
|
94 case element
|
|
95 when REXML::Text
|
|
96 element.value
|
|
97 when REXML::Node
|
|
98 case element.name.to_sym
|
|
99 when :uri
|
|
100 RDF::UriNode.new(element.text)
|
|
101 when :literal
|
|
102 RDF::PlainLiteralNode.new(element.text)
|
|
103 when :bnode
|
|
104 RDF::BlankNode.new(element.text, graph)
|
|
105 else
|
|
106 raise NotImplementedError # TODO
|
|
107 end
|
|
108 else
|
|
109 raise NotImplementedError # TODO
|
|
110 end
|
|
111 end
|
|
112
|
|
113 client
|
|
114 end
|
|
115
|
|
116 def search(client, query)
|
|
117 client.query(query)
|
|
118 end
|
|
119
|
|
120 def main(output)
|
|
121 client = create_customized_client(options[:endpoint])
|
|
122 search(client, options[:query]).each do |row|
|
|
123 output.puts row.join("\t")
|
|
124 end
|
|
125 end
|
|
126 end
|
|
127
|
|
128 if $0 == __FILE__
|
|
129 SPARQLExecutor.new.run(ARGV)
|
|
130 end
|