All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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