
function.datashape.ppath.rq Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of corese-core Show documentation
Show all versions of corese-core Show documentation
Corese is a Semantic Web Factory (triple store and SPARQL endpoint) implementing RDF, RDFS, SPARQL 1.1
Query and Update.
The newest version!
#
# Data Shape Property Path Interpreter
# RDF Path expression are compiled and stored as LDScript list by ppathparser
#
# Olivier Corby - Wimmics Inria I3S - 2016-2019
#
prefix sh:
prefix xsh:
prefix jc:
@import
#
# Return list of nodes related to node ?s by path ?p
# ?s is subject, ?p is PP expression
# ?s = us:John ; ?p = [sh:zeroOrMorePath foaf:knows]
#
function dt:list sh:ppath(s, p){
sh:path(sh:shaclGraph(), s, sh:getPPath(p), false)
}
function dt:list sh:path(dt:graph shape, s, p){
#xt:print("path:", sh:getPath(shape, p));
sh:path(shape, s, sh:getPath(shape, p), false)
}
# user api, evaluate SHACL path in SHACL RDF format
function sh:pathfinder(path, node) {
sh:evalpath(node, sh:getPPath(path))
}
function sh:pathfinder(path, node, asubject) {
sh:evalpath(asubject, node, sh:getPPath(path))
}
# user api, evaluate SHACL path in compiled path format
function sh:cpathfinder(path, node) {
sh:evalpath(node, path)
}
function sh:cpathfinder(path, node, asubject) {
sh:evalpath(asubject, node, path)
}
#
# Evaluate PP p as a list
# Return list of target nodes that match the path
# inv = true means within inverse path
#
function dt:list sh:path(shape, node, exp, xsd:boolean inv){
sh:evalpath(xt:list(), node, node, exp, inv, sh:null)
}
#
# Public extension function to be used out of SHACL
# evaluate path compiled as dt:list
#
function sh:evalpath(node, exp) {
sh:evalpath(xt:list(), node, node, exp, false, sh:null)
}
function sh:evalpath(asubject, node, exp) {
sh:evalpath(xt:list(), asubject, node, exp, false, sh:null)
}
# url = sh:null || server URL
# if null, triple patterns are evaluated on local dataset
# if not null, triple patterns are evaluated on SPARQL endpoint url with service url { s p o }
# focus is argument for (us:g1 us:g2) like select from
#
function dt:list sh:evalpath(focus, asubject, node, exp, xsd:boolean inv, url){
if (isExtension(exp)) { # dt:list
let ((oper path) = exp) {
return(funcall(oper, focus, asubject, node, path, inv, url))
}
}
else { # URI or *
return(sh:pathProperty(focus, asubject, node, exp, inv, url))
}
}
# exp is a list of path expressions
function dt:list sh:zeroOrOnePath(focus, asubject, node, exp, xsd:boolean inv, url){
let (nodeList = sh:evalpath(focus, asubject, node, exp, inv, url)){
if (xt:member(node, nodeList),
return(nodeList),
return(xt:cons(node, nodeList)))
}
}
function dt:list sh:zeroOrMorePath(focus, asubject, node, exp, xsd:boolean inv, url){
sh:rec(focus, asubject, node, exp, xt:list(node), inv, url)
}
function dt:list sh:oneOrMorePath(focus, asubject, node, exp, xsd:boolean inv, url){
sh:rec(focus, asubject, node, exp, xt:list(), inv, url)
}
#
# ?p is a PP expression exp
# compute exp*
# ?res is the list of nodes already reached by exp*
# ?res prevents loops
#
function dt:list sh:rec(focus, asubject, node, exp, dt:list res, xsd:boolean inv, url){
let (nodeList = sh:evalpath(focus, asubject, node, exp, inv, url)){
if (xt:size(nodeList) = 0){ return(res) }
else {
for (next in nodeList){
if (! xt:member(next, res)){
xt:add(res, next) ;
sh:rec(focus, asubject, next, exp, res, inv, url)
}
} ;
return(res)
}
}
}
#
# s ^exp
# inverse PP expression
#
function dt:list sh:inversePath(focus, asubject, node, exp, xsd:boolean inv, url){
sh:evalpath(focus, asubject, node, exp, ! inv, url)
}
#
# (sh:sequencePath (exp .. exp))
# exp = (exp .. exp)
#
function dt:list sh:sequencePath(focus, asubject, node, exp, xsd:boolean inv, url){
if (inv) {
return(sh:seqlist(focus, asubject, node, sh:reverse(exp), inv, url))
}
else{
return(sh:seqlist(focus, asubject, node, exp, inv, url))
}
}
# PRAGMA: correct when xsh:from is first statement
#
function sh:reverse(exp) {
if (sh:isFocus(xt:get(exp, 0)),
xt:cons(xt:get(exp, 0), xt:reverse(xt:rest(exp))),
xt:reverse(exp))
}
#
# Recursive traversal of sequence list expList
# recurse on xt:rest(expList)
# when sequence starts with [xsh:from (us:g1 us:g2)]
# rec call with focus = (us:g1 us:g2) like select from us:g1 us:g2
#
function dt:list sh:seqlist(focus, asubject, node, dt:list expList, xsd:boolean inv, url) {
if (xt:size(expList) = 0) {
# reach end of sequence: add target node subject
return(xt:list(node))
}
else {
let ((firstExp | restExpList) = expList) {
if (sh:isFocus(firstExp)) {
# rec call with from
sh:seqlist(sh:getFocus(firstExp), asubject, node, restExpList, inv, url)
}
else {
let (nodeList = sh:evalpath(focus, asubject, node, firstExp, inv, url)) {
return (sh:seqlistmap(focus, asubject, nodeList, restExpList, inv, url))
}
}
}
}
}
# [xsh:from (us:g1 us:g2)]
#
function sh:isFocus(exp) {
if (isExtension(exp)) {
let ((name rest) = exp) {
if (name = xsh:function) {
let ((oper arg) = rest) {
if (oper = xsh:from) {
return (true)
}
}
}
}
} ;
return (false)
}
# [xsh:from (us:g1 us:g2)]
# return (us:g1 us:g2)
#
function sh:getFocus(exp) {
let ((name rest) = exp,
(oper arg) = rest) {
return (arg)
}
}
# if next exp is service, we can execute it with values nodeList for focus nodes
#
function dt:list sh:seqlistmap(focus, asubject, nodeList, dt:list expList, xsd:boolean inv, url) {
let (res = xt:list()) {
for (next in nodeList) {
let (list = sh:seqlist(focus, asubject, next, expList, inv, url)) {
# merge removes duplicate nodes
set(res = xt:merge(res, list))
}
} ;
return (res)
}
}
# p = (sh:alternativePath (exp .. exp))
function dt:list sh:alternativePath(focus, asubject, node, exp, xsd:boolean inv, url){
let (expList = exp) {
#return(mapmerge(sh:pathmap, expList, xt:list(focus), asubject, node, inv, url))
return(mapmerge(sh:pathmap, expList, focus, asubject, node, inv, url))
}
}
function dt:list sh:pathmap(exp, focus, asubject, node, xsd:boolean inv, url){
sh:evalpath(focus, asubject, node, exp, inv, url)
}
# TODO: check inv
function dt:list sh:negativePath(focus, asubject, s, exp, inv, url){
let (select ?s ?exp (aggregate(?o) as ?l)
where { values ?exp {undef} ?s ?p ?o filter (?p != ?exp) }){
return(?l)
}
}
function dt:list sh:pathProperty(focus, asubject, node, p, xsd:boolean inv, url){
if (url = sh:null) {
if (inv) {
return(sh:inverse(focus, node, p))
}
else if (isLiteral(p)) { # p = *
return (sh:star(node))
}
else {
return(sh:step(focus, node, p))
}
}
else if (inv) {
return(sh:inverseService(node, p, url))
}
else if (isLiteral(p)) { # p = *
return (sh:starService(node, url))
}
else {
return(sh:predicateService(node, p, url))
}
}
function dt:list sh:step(focus, node, apredicate) {
if (xt:size(focus) > 0) {
xt:objects(node, apredicate, bnode(), focus)
}
else {
let (select (aggregate(distinct ?object) as ?list) node apredicate
where { ?node ?apredicate ?object }) {
return (list)
}
}
}
function dt:list sh:step2(focus, node, apredicate) {
xt:objects(node, apredicate, bnode(), focus)
}
function dt:list sh:inverse(focus, node, apredicate) {
if (xt:size(focus) > 0) {
xt:subjects(bnode(), apredicate, node, focus)
}
else {
let (select (aggregate(distinct ?subject) as ?list) node apredicate
where { ?subject ?apredicate ?node }) {
return (list)
}
}
}
function dt:list sh:inverse2(focus, node, apredicate){
xt:subjects(bnode(), apredicate, node, focus)
}
function sh:objects(focus, node, apredicate) {
maplist(xt:object, xt:edges(node, apredicate, bnode(), focus))
}
function sh:subjects(focus, node, apredicate) {
maplist(xt:subject, xt:edges(bnode(), apredicate, node, focus))
}
function dt:list sh:predicate2(?s, ?p){
let (select ?s ?p (aggregate(?o) as ?l) where { ?s ?p ?o }){
return(?l)
}
}
function dt:list sh:star(?s){
let (select ?s (aggregate(?o) as ?l) where { ?s ?p ?o }){
return(?l)
}
}
function dt:list sh:inverse2(?o, ?p){
let (select ?o ?p (aggregate(?s) as ?l) where { ?s ?p ?o }){
return(?l)
}
}
function dt:list sh:predicateService(?s, ?p, ?url){
if (us:trace(), xt:print("predicate service:", ?url, ?s, ?p), true);
if (isBlank(?s)) { return(xt:list()) } ;
let (select ?s ?p ?url (aggregate(?o) as ?l) where { service ?url { ?s ?p ?o } }){
if (us:trace(), xt:print("list:", l), true);
return(?l)
}
}
function dt:list sh:starService(?s, ?url){
if (us:trace(), xt:print("predicate service:", ?url, ?s), true);
if (isBlank(?s)) { return(xt:list()) } ;
let (select ?s ?url (aggregate(?o) as ?l) where { service ?url { ?s ?p ?o } }){
if (us:trace(), xt:print("list:", l), true);
return(?l)
}
}
function dt:list sh:inverseService(?o, ?p, ?url){
if (isBlank(?o)) { return(xt:list()) } ;
let (select ?o ?p ?url (aggregate(?s) as ?l) where { service ?url { ?s ?p ?o } }){
return(?l)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy