sparql
Version:
Simple, low-level SPARQL client
147 lines (127 loc) • 3.96 kB
text/coffeescript
request = require 'request'
querystring = require 'querystring'
normalize_v = (v) ->
return null unless v?
if v instanceof Array
if v.length is 0
return null
else
return v
else
return [v]
get_one_key = (obj) ->
for own k of obj
return k
compose_prefix_string = (prefix_map) ->
( "prefix #{k}: <#{v}>" for k, v of prefix_map ).join ' '
does_query_have_prefixes = (query) ->
# TODO: should be regex
# for now, simple heuristic. "prefix" must happen within the first 10 chars
iof = query.toLowerCase().indexOf 'prefix'
0 < iof < 10
ensure_prefixes = (query, prefix_map) ->
s = compose_prefix_string prefix_map
if s.length is 0 or does_query_have_prefixes query then query else s + ' ' + query
generate_set_sparql = ( g, s, p, o, inverted, cb ) ->
[e, a, v] = if inverted then [o, p, s] else [s, p, o]
v = normalize_v v
del = (if inverted then ['?x', a, e] else [e, a, '?x']).join ' '
if v?
ins = ((if inverted then [val, a, e] else [e, a, val]).join ' ' for val in v).join ' . '
q = "modify #{g} delete { #{del} } insert { #{ins} } where { optional{ #{del} } }"
else
q = "delete from #{g} { #{del} } where { #{del} } "
generate_mset_sparql = ( g, s, atts, cb ) ->
# This method doesn't check on anything, just issues an insert.
# If you want something safer (for now), you have to combine with get
qSjt = "insert into #{g} { #{s} "
# This is my hack to iterate over the atts object!
counter = 1
qAtt = for k,v of atts
if counter < Object.keys(atts).length
x = ";"
else
x = ""
counter = counter + 1
k + " '" + v + "' "+ x
q = qSjt + qAtt.join(" ") + ". }"
exports.ensure_prefixes = ensure_prefixes
exports.does_query_have_prefixes = does_query_have_prefixes
exports.compose_prefix_string = compose_prefix_string
exports.generate_set_sparql = generate_set_sparql
exports.generate_mset_sparql = generate_mset_sparql
class Client
constructor: ( @url ) ->
@prefix_map = {}
query : ( query, cb ) ->
query = ensure_prefixes query, @prefix_map
console?.log query if @log_query is true # quick n' dirty logging option
opts =
uri: @url
headers:
'content-type':'application/x-www-form-urlencoded'
'accept':'application/sparql-results+json'
body: querystring.stringify (query:query)
encoding: 'utf8'
request.post opts, (err, res, body) ->
if res?.statusCode is 200
cb? null, JSON.parse body
else
cb? [err, res, body]
rows : ( query, cb ) ->
@query query, (err, res) ->
if err?
cb err
return
if res?
cb null, res.results.bindings
else
cb null, null
cols : ( query, cb ) ->
@query query, (err, res) ->
if err?
cb err
return
if res?
r = {}
r[name] = ( row[name] for row in res.results.bindings ) for name in res.head.vars
cb null, r
else
cb null, null
cell : ( query, cb ) ->
@row query, (err, res) ->
if err?
cb err
return
if res?
cb null, res[ get_one_key res ]
else
cb null, null
row : ( query, cb ) ->
@query query, (err, res) ->
if err?
cb err
return
b = res.results.bindings
if b.length is 0
cb null, null
else
cb null, b[0]
col : ( query, cb ) ->
@query query, (err, res) ->
if err?
cb err
return
bs = res.results.bindings
if bs.length is 0
cb null, []
else
key = get_one_key bs[0]
cb null, (b[key] for b in bs)
set : ( g, s, p, o, inverted, cb ) ->
q = generate_set_sparql g, s, p, o, inverted
@query q, (err, res) -> cb? err, res
mset : ( g, s, atts, cb ) ->
q = generate_mset_sparql g, s, atts
@query q, (err, res) -> cb? err, res
exports.Client = Client