pho 0.5 → 0.6

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.
Files changed (80) hide show
  1. data/CHANGES +17 -0
  2. data/Rakefile +10 -2
  3. data/bin/talis_store +37 -92
  4. data/doc/rdoc/classes/Pho.html +11 -0
  5. data/doc/rdoc/classes/Pho/CommandLine.html +508 -0
  6. data/doc/rdoc/classes/Pho/DatatypeProperty.html +15 -15
  7. data/doc/rdoc/classes/Pho/Enrichment.html +1 -1
  8. data/doc/rdoc/classes/Pho/Enrichment/{ResourceEnricher.html → StoreEnricher.html} +158 -58
  9. data/doc/rdoc/classes/Pho/Etags.html +36 -36
  10. data/doc/rdoc/classes/Pho/Facet/Results.html +19 -19
  11. data/doc/rdoc/classes/Pho/Facet/Term.html +6 -6
  12. data/doc/rdoc/classes/Pho/FieldPredicateMap.html +94 -94
  13. data/doc/rdoc/classes/Pho/FieldWeighting.html +14 -14
  14. data/doc/rdoc/classes/Pho/FileManagement/AbstractFileManager.html +126 -91
  15. data/doc/rdoc/classes/Pho/FileManagement/FileManager.html +68 -62
  16. data/doc/rdoc/classes/Pho/FileManagement/RDFManager.html +22 -57
  17. data/doc/rdoc/classes/Pho/Job.html +68 -67
  18. data/doc/rdoc/classes/Pho/Jobs.html +62 -62
  19. data/doc/rdoc/classes/Pho/QueryProfile.html +64 -64
  20. data/doc/rdoc/classes/Pho/RDF.html +120 -0
  21. data/doc/rdoc/classes/Pho/RDF/Parser.html +277 -0
  22. data/doc/rdoc/classes/Pho/ResourceHash.html +1 -1
  23. data/doc/rdoc/classes/Pho/ResourceHash/Converter.html +48 -46
  24. data/doc/rdoc/classes/Pho/ResourceHash/SetAlgebra.html +15 -14
  25. data/doc/rdoc/classes/Pho/Snapshot.html +36 -36
  26. data/doc/rdoc/classes/Pho/Sparql.html +50 -0
  27. data/doc/rdoc/classes/Pho/Sparql/SparqlClient.html +147 -68
  28. data/doc/rdoc/classes/Pho/Sparql/SparqlHelper.html +195 -114
  29. data/doc/rdoc/classes/Pho/Status.html +26 -26
  30. data/doc/rdoc/classes/Pho/Store.html +271 -264
  31. data/doc/rdoc/classes/Pho/StoreSparqlClient.html +183 -0
  32. data/doc/rdoc/classes/Pho/Update.html +1 -0
  33. data/doc/rdoc/classes/Pho/Update/Changeset.html +69 -68
  34. data/doc/rdoc/classes/Pho/Update/ChangesetBuilder.html +24 -24
  35. data/doc/rdoc/classes/Pho/Update/Changesets.html +15 -14
  36. data/doc/rdoc/classes/Pho/Update/LiteralStatement.html +18 -18
  37. data/doc/rdoc/classes/Pho/Update/ResourceStatement.html +24 -24
  38. data/doc/rdoc/classes/Pho/Update/Statement.html +28 -27
  39. data/doc/rdoc/classes/String.html +1 -1
  40. data/doc/rdoc/created.rid +1 -1
  41. data/doc/rdoc/files/CHANGES.html +53 -1
  42. data/doc/rdoc/files/lib/pho/changeset_rb.html +1 -1
  43. data/doc/rdoc/files/lib/pho/command_line_rb.html +101 -0
  44. data/doc/rdoc/files/lib/pho/converter_rb.html +1 -1
  45. data/doc/rdoc/files/lib/pho/enrichment_rb.html +1 -1
  46. data/doc/rdoc/files/lib/pho/file_management_rb.html +1 -1
  47. data/doc/rdoc/files/lib/pho/file_manager_rb.html +1 -1
  48. data/doc/rdoc/files/lib/pho/rdf_collection_rb.html +1 -1
  49. data/doc/rdoc/files/lib/pho/rdf_rb.html +108 -0
  50. data/doc/rdoc/files/lib/pho/sparql_rb.html +1 -1
  51. data/doc/rdoc/files/lib/pho/store_rb.html +8 -1
  52. data/doc/rdoc/files/lib/pho_rb.html +4 -2
  53. data/doc/rdoc/fr_class_index.html +6 -1
  54. data/doc/rdoc/fr_file_index.html +2 -0
  55. data/doc/rdoc/fr_method_index.html +192 -172
  56. data/examples/calais/bio.txt +7 -0
  57. data/examples/calais/dump.rb +17 -0
  58. data/examples/calais/enlighten.rb +23 -0
  59. data/examples/calais/output.rdf +25 -0
  60. data/examples/sinatra/viewer.rb +20 -0
  61. data/lib/pho.rb +4 -1
  62. data/lib/pho/changeset.rb +17 -1
  63. data/lib/pho/command_line.rb +166 -0
  64. data/lib/pho/converter.rb +8 -3
  65. data/lib/pho/enrichment.rb +93 -28
  66. data/lib/pho/file_management.rb +32 -19
  67. data/lib/pho/file_manager.rb +22 -26
  68. data/lib/pho/rdf.rb +74 -0
  69. data/lib/pho/rdf_collection.rb +2 -17
  70. data/lib/pho/sparql.rb +150 -38
  71. data/lib/pho/store.rb +28 -2
  72. data/tests/tc_contentbox.rb +41 -0
  73. data/tests/tc_enrichment.rb +41 -4
  74. data/tests/tc_file_manager.rb +97 -7
  75. data/tests/tc_rdf_collection.rb +25 -13
  76. data/tests/tc_rdf_parser.rb +37 -0
  77. data/tests/tc_sparql.rb +72 -2
  78. data/tests/tc_sparql_helper.rb +16 -0
  79. data/tests/ts_pho.rb +2 -1
  80. metadata +20 -3
@@ -6,44 +6,40 @@ module Pho
6
6
 
7
7
  class FileManager < AbstractFileManager
8
8
 
9
- def initialize(store, dir, ok_suffix=OK, fail_suffix=FAIL, sleep=1)
9
+ attr_reader :base
10
+
11
+ def initialize(store, dir, base = nil, ok_suffix=OK, fail_suffix=FAIL, sleep=1)
10
12
  super(store, dir, ok_suffix, fail_suffix, sleep)
13
+ @base = base
11
14
  end
12
-
15
+
13
16
  #List files being managed, i.e. everything not .ok or .fail
14
- def list()
17
+ def list(recursive=false)
15
18
  files = []
16
- Dir.glob( File.join(@dir, "*") ) do |file|
17
- if File.extname(file) != ".#{@ok_suffix}" && File.extname(file) != ".#{@fail_suffix}"
19
+ if recursive
20
+ pattern = "**/*"
21
+ else
22
+ pattern = "*"
23
+ end
24
+ Dir.glob( File.join(@dir, pattern) ) do |file|
25
+ if File.extname(file) != ".#{@ok_suffix}" && File.extname(file) != ".#{@fail_suffix}" && !File.directory?(file)
18
26
  files << file
19
27
  end
20
28
  end
21
29
  return files
22
30
  end
23
-
24
- #List any new files in the directory
25
- def new_files()
26
- newfiles = Array.new
27
- Dir.glob( File.join(@dir, "*") ) do |file|
28
-
29
- if File.extname(file) != ".#{@ok_suffix}" && File.extname(file) != ".#{@fail_suffix}"
30
- ok_file = get_ok_file_for(file)
31
- fail_file = get_fail_file_for(file)
32
- if !( File.exists?(ok_file) or File.exists?(fail_file) )
33
- newfiles << file
34
- end
35
-
36
- end
37
-
38
- end
39
- return newfiles
40
- end
41
-
42
-
31
+
32
+ def FileManager.name_for_file(dir, file, base=nil)
33
+ uri = file.path.gsub(dir, "")
34
+ uri = "#{base}#{uri}" if base != nil
35
+ return uri
36
+ end
37
+
43
38
  protected
44
39
 
45
40
  def store_file(file, filename)
46
- response = @store.upload_item(file, MIME::Types.type_for(filename)[0].to_s )
41
+ uri = FileManager.name_for_file(@dir, file, @base)
42
+ response = @store.upload_item(file, MIME::Types.type_for(filename)[0].to_s, uri )
47
43
  if (response.status < 300 )
48
44
  File.open(get_ok_file_for(filename), "w") do |file|
49
45
  file.print( "OK" )
@@ -0,0 +1,74 @@
1
+ module Pho
2
+
3
+ #Module containing general RDF utilities and classes
4
+ #
5
+ #Dependent on the redland ruby bindings
6
+ module RDF
7
+
8
+ begin
9
+ require 'rdf/redland'
10
+ rescue LoadError
11
+ $stderr.puts "WARNING: Unable to load redland-ruby bindings. Some RDF utils will be unavailable"
12
+ end
13
+
14
+ #General RDF parsing utilities.
15
+ #
16
+ #Currently a convenience wrapper around the Redland Ruby bindings
17
+ class Parser
18
+
19
+ #Parse a file containing ntriples into RDF/XML. Returns a string
20
+ #
21
+ # file:: File object
22
+ # base_uri:: optional base uri to be used when parsing. If not set, then uris are resolved
23
+ # relative to the File
24
+ def Parser.parse_ntriples(file, base_uri=nil)
25
+ model = Redland::Model.new()
26
+ parser = Redland::Parser.new("ntriples", "")
27
+ uri = "file:#{file.path}"
28
+ base_uri = uri unless base_uri
29
+ parser.parse_into_model(model, uri, base_uri)
30
+ serializer = Redland::Serializer.new( "rdfxml", "application/rdf+xml" )
31
+ data = serializer.model_to_string(Redland::Uri.new(base_uri), model)
32
+ return data
33
+ end
34
+
35
+ #Parse a string containing ntriples into RDF/XML. Returns a string
36
+ #
37
+ # string:: the string containing the data
38
+ # base_uri:: base uri for parsing the data
39
+ def Parser.parse_ntriples_from_string(string, base_uri)
40
+ model = Redland::Model.new()
41
+ parser = Redland::Parser.new("ntriples", "")
42
+ parser.parse_string_into_model(model, string, Redland::Uri.new(base_uri))
43
+ serializer = Redland::Serializer.new( "rdfxml", "application/rdf+xml" )
44
+ data = serializer.model_to_string(Redland::Uri.new(base_uri), model)
45
+ return data
46
+ end
47
+
48
+ #Convenience method to parse an ntriples file and store it a Platform store
49
+ #
50
+ # file:: the file to parse
51
+ # store:: the store to receive the data
52
+ # base_uri:: base uri against which the data is parsed
53
+ # graph_name:: uri of graph in store
54
+ def Parser.store_ntriples(file, store, base_uri=nil, graph_name=nil)
55
+ data = Parser.parse_ntriples(file, base_uri)
56
+ return store.store_data(data, graph_name)
57
+ end
58
+
59
+ #Convenience method to parse an ntriples string and store it a Platform store
60
+ #
61
+ # string:: the data to parse
62
+ # store:: the store to receive the data
63
+ # base_uri:: base uri against which the data is parsed
64
+ # graph_name:: uri of graph in store
65
+ def Parser.store_ntriples_from_string(string, store, base_uri, graph_name=nil)
66
+ data = Parser.parse_ntriples_from_string(string, base_uri)
67
+ return store.store_data(data, graph_name)
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -14,26 +14,11 @@ module Pho
14
14
  super(store, dir, ok_suffix, fail_suffix, sleep)
15
15
  @rdf_suffix = rdf_suffix
16
16
  end
17
-
18
-
17
+
19
18
  #List files being managed
20
- def list()
19
+ def list(recursive=false)
21
20
  return Dir.glob( File.join(@dir, "*.#{@rdf_suffix}") )
22
21
  end
23
-
24
- #List any new files in the directory
25
- def new_files()
26
- newfiles = Array.new
27
- Dir.glob( File.join(@dir, "*.#{@rdf_suffix}") ) do |file|
28
- ok_file = get_ok_file_for(file)
29
- fail_file = get_fail_file_for(file)
30
- if !( File.exists?(ok_file) or File.exists?(fail_file) )
31
- newfiles << file
32
- end
33
- end
34
- return newfiles
35
- end
36
-
37
22
 
38
23
  protected
39
24
 
@@ -7,6 +7,90 @@ module Pho
7
7
  SPARQL_RESULTS_XML = "application/sparql-results+xml"
8
8
  SPARQL_RESULTS_JSON = "application/sparql-results+json"
9
9
 
10
+ #Includes all statements along both in-bound and out-bound arc paths
11
+ #
12
+ #See http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF
13
+ SYMMETRIC_BOUNDED_DESCRIPTION = <<-EOL
14
+ CONSTRUCT {?uri ?p ?o . ?s ?p2 ?uri .} WHERE { {?uri ?p ?o .} UNION {?s ?p2 ?uri .} }
15
+ EOL
16
+
17
+ #Similar to Concise Bounded Description but includes labels for referenced resources
18
+ #
19
+ #See http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF
20
+ LABELLED_BOUNDED_DESCRIPTION = <<-EOL
21
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
22
+ CONSTRUCT {
23
+ ?uri ?p ?o .
24
+ ?o rdfs:label ?label .
25
+ ?o rdfs:comment ?comment .
26
+ ?o <http://www.w3.org/2004/02/skos/core#prefLabel> ?plabel .
27
+ ?o rdfs:seeAlso ?seealso.
28
+ } WHERE {
29
+ ?uri ?p ?o .
30
+ OPTIONAL {
31
+ ?o rdfs:label ?label .
32
+ }
33
+ OPTIONAL {
34
+ ?o <http://www.w3.org/2004/02/skos/core#prefLabel> ?plabel .
35
+ }
36
+ OPTIONAL {
37
+ ?o rdfs:comment ?comment .
38
+ }
39
+ OPTIONAL {
40
+ ?o rdfs:seeAlso ?seealso.
41
+ }
42
+ }
43
+ EOL
44
+
45
+ #Derived from both the Symmetric and Labelled Bounded Descriptions. Includes all in-bound
46
+ #and out-bound arc paths, with labels for any referenced resources.
47
+ #
48
+ #See http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF
49
+ SYMMETRIC_LABELLED_BOUNDED_DESCRIPTION = <<-EOL
50
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
51
+ CONSTRUCT {
52
+ ?uri ?p ?o .
53
+ ?o rdfs:label ?label .
54
+ ?o rdfs:comment ?comment .
55
+ ?o rdfs:seeAlso ?seealso.
56
+ ?s ?p2 ?uri .
57
+ ?s rdfs:label ?label .
58
+ ?s rdfs:comment ?comment .
59
+ ?s rdfs:seeAlso ?seealso.
60
+ } WHERE {
61
+ { ?uri ?p ?o .
62
+ OPTIONAL {
63
+ ?o rdfs:label ?label .
64
+ }
65
+ OPTIONAL {
66
+ ?o rdfs:comment ?comment .
67
+ }
68
+ OPTIONAL {
69
+ ?o rdfs:seeAlso ?seealso.
70
+ }
71
+ }
72
+ UNION {
73
+ ?s ?p2 ?uri .
74
+ OPTIONAL {
75
+ ?s rdfs:label ?label .
76
+ }
77
+ OPTIONAL {
78
+ ?s rdfs:comment ?comment .
79
+ }
80
+ OPTIONAL {
81
+ ?s rdfs:seeAlso ?seealso.
82
+ }
83
+ }
84
+ }
85
+ EOL
86
+
87
+ DESCRIPTIONS = {
88
+ :cbd => "DESCRIBE ?uri",
89
+ :scbd => SYMMETRIC_BOUNDED_DESCRIPTION,
90
+ :lcbd => LABELLED_BOUNDED_DESCRIPTION,
91
+ :slcbd => SYMMETRIC_LABELLED_BOUNDED_DESCRIPTION
92
+ }
93
+
10
94
  #A simple SPARQL client that handles the basic HTTP traffic
11
95
  class SparqlClient
12
96
 
@@ -29,8 +113,8 @@ module Pho
29
113
 
30
114
  #Initialize a client for a specific endpoint
31
115
  #
32
- # endpoint:: uri of the SPARQL endpoint
33
- # client:: optionally, a reference to an existing HTTPClient object instance
116
+ #endpoint:: uri of the SPARQL endpoint
117
+ #client:: optionally, a reference to an existing HTTPClient object instance
34
118
  def initialize(endpoint, client=HTTPClient.new() )
35
119
  @endpoint = endpoint
36
120
  @graphs = nil
@@ -59,10 +143,10 @@ module Pho
59
143
 
60
144
  #Perform a sparql query
61
145
  #
62
- # sparql:: a valid SPARQL query
63
- # format:: specific a request format. Usually a media-type, but may be a name for a type, if not using Conneg
64
- # graphs:: an array of default graphs
65
- # named_graphs:: an array of named graphs
146
+ #sparql:: a valid SPARQL query
147
+ #format:: specific a request format. Usually a media-type, but may be a name for a type, if not using Conneg
148
+ #graphs:: an array of default graphs
149
+ #named_graphs:: an array of named graphs
66
150
  def query(sparql, format=nil, graphs=nil, named_graphs=nil)
67
151
 
68
152
  params = {}
@@ -94,10 +178,24 @@ module Pho
94
178
  return @client.get( @endpoint, params, headers )
95
179
  end
96
180
 
181
+ #Describe a uri, optionally specifying a form of bounded description
182
+ #
183
+ #uri:: the uri to describe
184
+ #format:: mimetype for results
185
+ #type:: symbol indicating type of description, i.e. +:cbd+, +:scbd+, +:lcbd+, or +:slcbd+
186
+ def describe_uri(uri, format="application/rdf+xml", type=:cbd)
187
+ template = Pho::Sparql::DESCRIPTIONS[type]
188
+ if template == nil
189
+ raise "Unknown description type"
190
+ end
191
+ query = Pho::Sparql::SparqlHelper.apply_initial_bindings(template, {"uri" => "<#{uri}>"} )
192
+ return describe(query, format)
193
+ end
194
+
97
195
  #Perform a SPARQL DESCRIBE query.
98
196
  #
99
- # query:: the SPARQL query
100
- # format:: the preferred response format
197
+ #query:: the SPARQL query
198
+ #format:: the preferred response format
101
199
  def describe(query, format="application/rdf+xml")
102
200
  return query(query, format)
103
201
  end
@@ -108,8 +206,8 @@ module Pho
108
206
  #This will generate a query like:
109
207
  # DESCRIBE <http://www.example.org> <http://www.example.com> ...
110
208
  #
111
- # uris:: list of the uris to be described
112
- # format:: the preferred response format. Default is RDF/XML
209
+ #uris:: list of the uris to be described
210
+ #format:: the preferred response format. Default is RDF/XML
113
211
  def multi_describe(uris, format="application/rdf+xml")
114
212
  query = "DESCRIBE " + uris.map {|u| "<#{u}>" }.join(" ")
115
213
  return query(query, format)
@@ -117,24 +215,24 @@ module Pho
117
215
 
118
216
  #Perform a SPARQL CONSTRUCT query.
119
217
  #
120
- # query:: the SPARQL query
121
- # format:: the preferred response format
218
+ #query:: the SPARQL query
219
+ #format:: the preferred response format
122
220
  def construct(query, format="application/rdf+xml")
123
221
  return query(query, format)
124
222
  end
125
223
 
126
224
  #Perform a SPARQL ASK query.
127
225
  #
128
- # query:: the SPARQL query
129
- # format:: the preferred response format
226
+ #query:: the SPARQL query
227
+ #format:: the preferred response format
130
228
  def ask(query, format=Pho::Sparql::SPARQL_RESULTS_XML)
131
229
  return query(query, format)
132
230
  end
133
231
 
134
232
  #Perform a SPARQL SELECT query.
135
233
  #
136
- # query:: the SPARQL query
137
- # format:: the preferred response format
234
+ #query:: the SPARQL query
235
+ #format:: the preferred response format
138
236
  def select(query, format=Pho::Sparql::SPARQL_RESULTS_XML)
139
237
  return query(query, format)
140
238
  end
@@ -154,8 +252,8 @@ module Pho
154
252
  #Any keys in the hash that are not in the query are ignored. Any variables not found
155
253
  #in the hash remain unbound.
156
254
  #
157
- # query:: the query whose initial bindings are to be set
158
- # values:: hash of query name to value
255
+ #query:: the query whose initial bindings are to be set
256
+ #values:: hash of query name to value
159
257
  def SparqlHelper.apply_initial_bindings(query, bindings={})
160
258
  copy = query.clone()
161
259
  copy.gsub!(VARIABLE_MATCHER) do |pattern|
@@ -180,7 +278,7 @@ module Pho
180
278
  #performed to extract some variables that can later be plugged into a subsequent
181
279
  #query
182
280
  #
183
- # result:: hash conforming to structure of a <tt>binding</tt> in the SPARQL JSON format
281
+ #result:: hash conforming to structure of a <tt>binding</tt> in the SPARQL JSON format
184
282
  def SparqlHelper.result_to_query_binding(result)
185
283
  hash = {}
186
284
  result.each_pair do |key, value|
@@ -202,10 +300,10 @@ module Pho
202
300
  #into the results.
203
301
  #
204
302
  #E.g:
205
- # <tt>results = Pho::Sparql::SparqlHelper.select(query, sparql_client)</tt>
206
- # <tt>bindings = Pho::Sparql::SparqlHelper.results_to_query_bindings(results)</tt>
303
+ #<tt>results = Pho::Sparql::SparqlHelper.select(query, sparql_client)</tt>
304
+ #<tt>bindings = Pho::Sparql::SparqlHelper.results_to_query_bindings(results)</tt>
207
305
  #
208
- # results:: hash conforming to SPARQL SELECT structure
306
+ #results:: hash conforming to SPARQL SELECT structure
209
307
  def SparqlHelper.results_to_query_bindings(results)
210
308
  bindings = []
211
309
 
@@ -221,8 +319,8 @@ module Pho
221
319
  #
222
320
  #An error will be raised if the response is HTTP OK.
223
321
  #
224
- # query:: the SPARQL SELECT query
225
- # sparql_client:: a configured SparqlClient object
322
+ #query:: the SPARQL SELECT query
323
+ #sparql_client:: a configured SparqlClient object
226
324
  def SparqlHelper.select(query, sparql_client)
227
325
  #TODO: test whether endpoint supports json, and if not, switch to parsing XML
228
326
  resp = sparql_client.select(query, Pho::Sparql::SPARQL_RESULTS_JSON)
@@ -237,8 +335,8 @@ module Pho
237
335
  #Will request the results using the SPARQL JSON results format, parse the
238
336
  #resulting JSON results, and extract the true/false response.
239
337
  #
240
- # query:: the SPARQL SELECT query
241
- # sparql_client:: a configured SparqlClient object
338
+ #query:: the SPARQL SELECT query
339
+ #sparql_client:: a configured SparqlClient object
242
340
  def SparqlHelper.ask(query, sparql_client)
243
341
  json = SparqlHelper.select(query, sparql_client)
244
342
  return json["boolean"] == "true"
@@ -252,8 +350,8 @@ module Pho
252
350
  #
253
351
  #Note this will lose any type information, only the value of the bindings are returned
254
352
  #
255
- # query:: the SPARQL SELECT query
256
- # sparql_client:: a configured SparqlClient object
353
+ #query:: the SPARQL SELECT query
354
+ #sparql_client:: a configured SparqlClient object
257
355
  def SparqlHelper.select_values(query, sparql_client)
258
356
  results = SparqlHelper.select(query, sparql_client)
259
357
  v = results["head"]["vars"][0];
@@ -272,8 +370,8 @@ module Pho
272
370
  #
273
371
  #Note this will lose any type information, only the value of the binding is returned
274
372
  #
275
- # query:: the SPARQL SELECT query
276
- # sparql_client:: a configured SparqlClient object
373
+ #query:: the SPARQL SELECT query
374
+ #sparql_client:: a configured SparqlClient object
277
375
  def SparqlHelper.select_single_value(query, sparql_client)
278
376
  results = SparqlHelper.select(query, sparql_client)
279
377
  v = results["head"]["vars"][0];
@@ -285,8 +383,8 @@ module Pho
285
383
  #Will request the results as application/json (with the expectation that it returns RDF_JSON),
286
384
  #and parses the resulting JSON document.
287
385
  #
288
- # query:: the SPARQL SELECT query
289
- # sparql_client:: a configured SparqlClient object
386
+ #query:: the SPARQL SELECT query
387
+ #sparql_client:: a configured SparqlClient object
290
388
  def SparqlHelper.construct_to_resource_hash(query, sparql_client)
291
389
  #TODO: test whether endpoint supports json, and if not, switch to parsing XML
292
390
  resp = sparql_client.construct(query, "application/json")
@@ -301,8 +399,8 @@ module Pho
301
399
  #Will request the results as application/json (with the expectation that it returns RDF_JSON),
302
400
  #and parses the resulting JSON document.
303
401
  #
304
- # query:: the SPARQL SELECT query
305
- # sparql_client:: a configured SparqlClient object
402
+ #query:: the SPARQL SELECT query
403
+ #sparql_client:: a configured SparqlClient object
306
404
  def SparqlHelper.describe_to_resource_hash(query, sparql_client)
307
405
  #TODO: test whether endpoint supports json, and if not, switch to parsing XML
308
406
  resp = sparql_client.describe(query, "application/json")
@@ -311,11 +409,11 @@ module Pho
311
409
  end
312
410
  return Pho::ResourceHash::Converter.parse_json( resp.content )
313
411
  end
314
-
412
+
315
413
  #DESCRIBE multiple resources in a single SPARQL request
316
414
  #
317
- # uris:: an array of URIs
318
- # sparql_client:: a configured SparqlClient objec
415
+ #uris:: an array of URIs
416
+ #sparql_client:: a configured SparqlClient objec
319
417
  def SparqlHelper.multi_describe(uris, sparql_client)
320
418
  #TODO: test whether endpoint supports json, and if not, switch to parsing XML
321
419
  resp = sparql_client.multi_describe(uris, "application/json")
@@ -324,7 +422,21 @@ module Pho
324
422
  end
325
423
  return Pho::ResourceHash::Converter.parse_json( resp.content )
326
424
  end
327
-
425
+
426
+ #Describe a single URI using one of several forms of Bounded Description
427
+ #See SparqlClient.describe_uri
428
+ #
429
+ #uri:: resource to describe
430
+ #sparql_client:: configured SPARQL client
431
+ #type:: form of bounded description to generate
432
+ def SparqlHelper.describe_uri(uri, sparql_client, type=:cbd)
433
+ #TODO: test whether endpoint supports json, and if not, switch to parsing XML
434
+ resp = sparql_client.describe_uri(uri, "application/json", type)
435
+ if resp.status != 200
436
+ raise "Error performing sparql query: #{resp.status} #{resp.reason}\n#{resp.content}"
437
+ end
438
+ return Pho::ResourceHash::Converter.parse_json( resp.content )
439
+ end
328
440
  end
329
441
 
330
442
  end