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

function.datashape.core.rq Maven / Gradle / Ivy

#
# SHACL Interpreter 
#
# Olivier Corby - Wimmics Inria I3S - 2016-2019
#

prefix sh:   
prefix msh: 
prefix shex: 

function sh:core(report, sh, vis, nodeList) {
    sh:core(report, sh, vis, nodeList, false)
}

#
# main function
# sh: current shape
# vis: true if report is needed
# nodeList:  list of target nodes of shape sh
# present=true: fail if path is empty (when there is a path)
#
function sh:core(report, sh, vis, nodeList, present) {
    if (sh:trace(), xt:print("core:", sh, nodeList, present), true);
    let (res = true) {
        for (node in dt:list(nodeList)) {
            if (sh:contains(sh, node)) {}
            else {
                sh:push(sh, node);
                let (suc = sh:pathcore(report, sh, vis, node, present)) {
                    if (suc || vis, set (suc = sh:booleancore   (report, sh, vis, node, present) && suc), true) ;
                    if (suc || vis, set (suc = sh:constraintcore(report, sh, vis, node, present) && suc), true);
                    if (suc || vis, set (suc = sh:closedcore    (report, sh, vis, node) && suc), true); 
                    set(res = res && suc)  
                } ;
                sh:pop()
            }
        } ;
        return (res)
    }
}

function sh:core22(report, sh, vis, nodeList, present) {
    if (sh:trace(), xt:print("core:", sh, nodeList, present), true);
    let (res = sh:pathcore(report, sh, vis, nodeList, present)) {
        if (res || vis, set (res = sh:booleancore   (report, sh, vis, nodeList, present) && res), true) ;
        if (res || vis, set (res = sh:constraintcore(report, sh, vis, nodeList, present) && res), true);
        if (res || vis, set (res = sh:closedcore    (report, sh, vis, nodeList) && res), true); 
        return (res)    
    }
}


# user api
function sh:eval(shape, node) {
    sh:core(sh:validationReport(), shape, false, dt:list(node), false)
}

function sh:closedcore(report, sh, vis, s) {
    let (res = true) {
        if (sh:isClosed(sh)) {
            let (predList = sh:getPredicates(sh)) {
                #xt:print("closed:", sh, predList);
                if (sh:trace(), xt:print("core closed:", sh, nodeList), true); 
                    for (select * where {?s ?p ?o}) {
                        let (suc = xt:member(p, predList)) {
                            #if (suc, true, xt:print("closed fail:", s, p, o, vis, sh, predList));
                            if (suc, true, set(res = false));
                            sh:report(report, sh:closed, sh, s, p, o, suc, vis)
                        }
                    }
            }
        } ;
        return (res)
    } 
}

function sh:closedcore2(report, sh, vis, node) {
    let (res = true) {
        if (sh:isClosed(sh)) {
            let (anypred = bnode(), predList = sh:getPredicates(sh)) {
                #xt:print("closed:", sh, predList);
                if (sh:trace(), xt:print("core closed:", sh, nodeList), true); 
                    for ((s p o) in xt:edges(node, anypred)) {
                        let (suc = xt:member(p, predList)) {
                            #if (suc, true, xt:print("closed fail:", s, p, o, vis, sh, predList));
                            if (suc, true, set(res = false));
                            sh:report(report, sh:closed, sh, s, p, o, suc, vis)
                        }
                    }
            }
        } ;
        return (res)
    } 
}
 

function sh:pathcore(report, sh, vis, nodeList, present) {
    let (res = true, cstList = sh:getShapeConstraint(sh:pathcore, sh)) {
        if (sh:trace(), xt:print("core path:", sh, cstList, present), true);
        for ((cst path) in cstList) {
            if (sh:trace(), xt:print("core path:", sh, nodeList), true); 
            let (suc = coalesce(sh:path(report, cst, vis, nodeList, path, present), false)) {
                if (suc, true, set(res = false))
            }
        } ;
        return (res)
    }
}


function sh:booleancore(report, sh, vis, nodeList, present) {
    #xt:print("core boolean:", sh, sh:getShapeConstraint(sh:booleancore,  sh));
    let (res = true) {
        for ((bool cst) in sh:getShapeConstraint(sh:booleancore,  sh)) {
            if (sh:trace(), xt:print("core boolean:", sh, nodeList), true); 
            let (suc = coalesce(funcall(msh:fun(bool), report, bool, sh, cst, vis, nodeList, present), false)) {
                if (suc, true, set(res = false))
            }
        } ;
        return (res)
    }
}

function sh:constraintcore(report, sh, vis, nodeList, present) {
    let (cst = sh:getShapeConstraint(sh:constraintcore, sh)) {
        if (cst) {
            if (sh:trace(), xt:print("core constraint:", sh, nodeList), true); 
            let (suc = sh:constraint(report, sh, vis, nodeList, present)) {
                return (suc)
            }
        }
        else {
            return (true)
        }
    }
}






function sh:getConstraint(name, shape, sh) {
    sh:getShapeConstraint(name,  sh)
}

function sh:isClosed(sh) {
    sh:getShapeConstraint(sh:isclosedcore, sh)
}

function sh:getPredicates(sh) {
    sh:getShapeConstraint(sh:closedcore, sh)
}

function sh:isclosedcore(shape, sh) {
    let (suc = exists { graph ?shape { ?sh sh:closed true } } ) {
        return (suc)
    }
}

function sh:closedcore(shape, sh) {
    let (select * (aggregate(distinct ?p) as ?list)
         where {
            graph ?shape {    
                ?sh sh:closed true                 
                { ?sh sh:property [ sh:path ?p ] filter isURI(?p) }
                union
                { ?sh sh:ignoredProperties/rdf:rest*/rdf:first ?p }
            }
         } ) {
         return (list)
    }
}

function sh:constraintcore(shape, sh) {
    let (suc = exists { graph ?shape { values ?sh { UNDEF } filter not exists { ?sh sh:path ?ppp } } } ) {
        return (suc)
    }
}



function sh:pathcore(shape, sh) {
    let (select * (aggregate(xt:list(coalesce(?cst, ?sh), ?p)) as ?list) 
        where {
            graph ?shape {  
                {?sh sh:property ?cst . ?cst sh:path ?p 
                filter not exists { ?cst sh:deactivated true } }
                union
                {?sh sh:path ?p  filter not exists { ?sh sh:deactivated true}}
            } } ) {
        return (list)
    }
}


function sh:booleancore(shape, sh) {
    sh:getGenericShape(shape, sh, sh:getShape(sh:boolean))
}

function sh:isdetail(sh) {
    sh:getShapeConstraint(sh:detail, sh)
}

function sh:detail(shape, sh) {
    let (select * where {
            graph ?shape {  
                ?sh sh:detail ?bb
            }
        }) {
        bound(bb) && bb 
    }
}




function msh:fun(name) {
    if (name = sh:not, msh:not, msh:boolean)
}

#
# sh : main shape
# cst : shape argument of sh:not [ cst ]
#
function msh:not (report, oper, sh, cst, vis, s, present) {
    let (res = true) {
            let (suc = coalesce(! sh:core(report, cst, false, s, present), false)) {
                if (suc, true, set(res = false));
                sh:report(report, sh:not, sh, s, sh:null, s,  suc, vis)
            }
        ;
        return (res)
    }
}

#
# oper = sh:and | sh:or | sh:xone 
# sh:  main shape
# cst: boolean shape, i.e. bnode value of sh:or ()
#
function msh:boolean (report, oper, sh, cst, vis, s, present) {
    let (res = true) {
                    
            let (suc = coalesce(
                    funcall(oper, report, sh, cst, sh:getCstList(oper, cst), s, sh:null, s, vis, present), 
                    false)) {
    
                #sh:report(report, oper, sh, s, sh:null, s, suc, vis); 
                                                
                if (suc, true, set (res = false))
            }
         ;
        return(res)
    }
}

#
# these boolean functions are called by core and path, hence we need s p o
#

# count fail
function xsd:boolean sh:and(report, sh, cst, cstList, s, p, o, vis, present) {
    sh:bool(report, sh:and, sh, cst, cstList, s, p, o, vis, present, 
        function (suc) {if (suc, 0, 1)}, function (nb) {nb = 0})
}


# count success
function xsd:boolean sh:or(report, sh, cst, cstList, s, p, o, vis, present) {
    sh:bool(report, sh:or, sh, cst, cstList, s, p, o, vis, present, 
        function (suc) {if (suc, 1, 0)}, function(nb) {nb > 0})
}


# count success
function xsd:boolean sh:xone(report, sh, cst, cstList, s, p, o, vis, present) {
    sh:bool(report, sh:xone, sh, cst, cstList, s, p, o, vis, present, 
        function (suc) {if (suc, 1, 0)}, function(nb) {nb = 1}) 
}


#  
# oper:  boolean operator
# cst: boolean shape, i.e. bnode value of sh:or ()
# cstList: list of statements of boolean shape
# detail:  [] xsh:booleanDetail true   
# sh:isdetail(cst): cst sh:detail true
#
function xsd:integer sh:bool(report, oper, sh, cst, cstList, s, p, o, vis, present, funincr, funsuc) {
   let (cc = 0, nodeList = xt:list(o), 
        detail      = vis && sh:isSetup(xsh:booleanDetail),
        subReport   = sh:detailReport(report, detail)) {
        for (cst in cstList) {
            let (res = sh:core(subReport, cst, detail, nodeList, present)) {  
                 set (cc = cc +  funcall(funincr, res))  
            }
        } ;
                
        let (suc = funcall(funsuc, cc)) {
            if (vis, sh:reportDetail(report, subReport, oper, sh, s, p, o, suc, vis, detail), true); 
            return(suc)
        }
    }
}




function sh:getCstList(oper, cst) {
    sh:getShapeConstraint(if (oper = shex:count, sh:countboolean, sh:coreboolean), cst)
}


function sh:coreboolean(shape, cst) {
     let ( 
        SELECT ?cst  ?shape (aggregate(?sh) as ?list)
		WHERE {
            graph ?shape { 
                ?cst rdf:rest*/rdf:first ?sh
            } } ) {  
            return (list)
        }
}




















© 2015 - 2025 Weber Informatics LLC | Privacy Policy