function.datashape.sparql.rq Maven / Gradle / Ivy
prefix sh:
function sh:sparql(report, sh, vis, nodeList, p) {
let (b1 = sh:sparqlbasic(report, sh, vis, nodeList, p),
b2 = sh:sparqlvalid(report, sh, vis, nodeList, p)) {
return (b1 && b2)
}
}
#
# sparql with path
#
function sh:sparqlbasic(report, sh, vis, nodeList, p) {
let (suc = true) {
for ((cst define q mes amin amax) in sh:getShapeConstraint(sh:cstsparql, sh)) {
let (funList = sh:getShapeConstraint(sh:sparqlfunction, cst)) {
for (node in dt:list(nodeList)) {
for (aobject in sh:ppath(node, p)) {
if (sh:trace(), xt:print("path sparql:", node, p, aobject, q), true);
let (res = sh:mysparql(report, concat(define, q), sh, cst, node, aobject, vis,
coalesce(mes, sh:null), bound(mes), amin, amax, funList)) {
if (res, true, set(suc = false))
}
}
}
}
};
return (suc)
}
}
#
# sparql without path
#
function sh:cstsparql (report, sh, vis, nodeList, cstList) {
let (res = true) {
for ((cst define q mes amin amax) in cstList) {
let (funList = sh:getShapeConstraint(sh:sparqlfunction, cst)) {
for (node in dt:list(nodeList)) {
if (sh:trace(), xt:print("cstsparql:", node, q), true);
let (suc = coalesce(
sh:mysparql(report, concat(define, q), sh, cst, node, node, vis,
mes, isLiteral(mes), amin, amax, funList),
false)) {
if (suc, true, set(res = false))
}
}
}
};
return (res)
}
}
#
# SPARQL constraint
# focus is the focus node, val is the value of focus to be tested
# for constraint: they are the same, for path: focus=subject ; val=object
# Query MUST return variables: ?this ?path ?value
#
function sh:mysparql(report, q, sh, cst, focus, val, vis, mes, hasmes, amin, amax, funList) {
let (maps = xt:sparql(q, "$this", val)) {
# if (xt:size(maps) > 0, xt:print("sparql:", maps), true);
if (xt:size(funList) > 0 || amin >= 0 || amax >= 0) {
# query return solutions not considered as errors: check amin <= size <= amax
sh:mysparqlext(report, q, sh, cst, focus, val, vis, mes, hasmes, amin, amax, funList, maps)
}
else {
# query return solutions as errors
for (m in maps) {
let ((path value) = m) {
if (hasmes) {
let (mmes = sh:mymessage(mes, m)) {
# xt:print(mmes);
# suc = false
sh:report(report, sh:sparql, sh, focus, path, value, false, vis)
}
}
else {
# suc = false
sh:report(report, sh:sparql, sh, focus, path, value, false, vis)
}
}
} ;
# results are errors
return (size = 0)
}
}
}
#
# xsh:function [ us:mytest(exp) ] --> function us:mytest(cst, focus, maps, exp)
# check number of results: sh:minCount sh:maxCount
#
function sh:mysparqlext(report, q, sh, cst, focus, val, vis, mes, hasmes, amin, amax, funList, maps) {
let (res = true) {
if (xt:size(funList) > 0) {
# xsh:function
for ((oper name exp) in funList) {
let (suc = funcall(name, cst, focus, maps, exp)) {
sh:report(report, sh:sparqlFunction, sh, focus, sh:sparql, name, suc, vis) ;
set (res = res && suc)
}
}
} ;
if (amin >= 0 || amax >= 0) {
# query return solutions as "success": check amin <= size <= amax
let (size = xt:size(maps),
suc = amin <= size && if (amax >= 0, size <= amax, true)) {
sh:report(report, sh:sparqlCount, sh, focus, sh:sparql, size, suc, vis) ;
set (res = res && suc)
}
} ;
return (res)
}
}
function sh:sparqlfunction(shape, sh) {
sh:getSparqlExtension(shape, sh)
}
#
# sparql with parameters
#
function sh:sparqlvalid (report, sh, vis, nodeList, p) {
let (res = true) {
for ((cst define q oper value) in sh:getShapeConstraint(sh:sparqlvalid, sh)) {
xt:print("sparql:", define, oper, value, q);
for (s in dt:list(nodeList)) {
let (suc = coalesce(
sh:sparqlvalidp(report, sh, cst, define, q, vis, s, p, oper, value),
false) ) {
if (suc, true, set(res = false))
}
}
} ;
return (res)
}
}
# replace {?var} by {val} in message
function sh:mymessage(xsd:string mes, dt:mapping m) {
for ((var val) in m) {
let (pat = concat('{', var, '}')) {
if (contains(mes, pat), set(mes = xt:replace(mes, pat, concat('{', val, '}'))), true)
}
} ;
return(mes)
}
function sh:cstsparql(shape, sh) {
let (select *
(aggregate (xt:list(cst, define, q, coalesce(mes, sh:null), coalesce(?min, -1), coalesce(?max, -1))) as ?list)
where {
graph ?shape {
?sh sh:sparql ?cst
?cst sh:select ?q
filter not exists { ?cst sh:deactivated true }
optional { ?cst sh:message ?mes }
optional { ?cst sh:minCount ?min }
optional { ?cst sh:maxCount ?max }
# collect prefix definitions
{
select ?cst
(group_concat(concat("prefix ", ?pr, ": <", str(?ns), ">") ; separator=" ")
as ?define)
where {
?cst sh:prefixes/owl:imports*/sh:declare [ sh:prefix ?pr ; sh:namespace ?ns ]
}
group by ?cst
}
} }
) {
return(list)
}
}
function sh:sparqlvalid(?shape, ?sh) {
let (select * (aggregate(xt:list(?cst, ?define, ?q, ?oper, ?value)) as ?list)
where {
graph ?shape {
?sh ?oper ?value
#filter (! sh:isPredicate(?oper))
filter (! mapany (rq:strstarts, ?oper, xt:list(sh:, xsh:, rdfs:, owl:, rdf:)))
?cst sh:parameter [ sh:path ?oper ] ;
sh:propertyValidator ?valid
?valid sh:select ?q
filter not exists { ?cst sh:deactivated true }
# collect prefix definitions
{
select ?valid
(group_concat(concat("prefix ", ?pr, ": <", str(?ns), ">") ; separator=" ")
as ?define)
where {
?valid sh:prefixes/owl:imports*/sh:declare [ sh:prefix ?pr ; sh:namespace ?ns ]
}
group by ?valid
}
} } ) {
return (list)
}
}
function sh:sparqlvalidp (report, sh, cst, define, q, vis, s, p, oper, obj) {
let (res = true, var = sh:variable(oper),
qq = concat(define, replace(q, "\\$PATH", sh:display(sh:shaclGraph(), p)), sh:values(var))) {
for ((value) in xt:sparql(qq, "$this", s, var, obj)) {
# SPARQL query returns solutions that fail
let (suc = false) {
set (res = false);
sh:report(report, cst, sh, cst, s, p, value, suc, vis)
}
} ;
return (res)
}
}
function sh:display(?shape, ?p) {
if (isURI(?p), st:turtle(?p), st:apply-templates-with-graph(st:dspprint, ?shape, ?p))
}
function sh:variable(?uri) {
concat("?", xt:strip(?uri))
}
# pseudo declare variables in case they are not in a triple of query ?q
function sh:values(?oper){
concat("values (?this ", ?oper, ") { (UNDEF UNDEF) }")
}
function sh:isPredicate(?p) {
strstarts(?p, sh:) || strstarts(?p, rdfs:) || strstarts(?p, rdf:) || strstarts(?p, owl:)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy