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

function.datashape2.report.rq Maven / Gradle / Ivy

#
# SHACL Interpreter 
#
# Olivier Corby - Wimmics Inria I3S - 2016-2020
#
prefix sh:    
prefix xsh:   
prefix shex: 

#
# suc is success/failure of the shape
# vis true means generate a ValidationResult
#
function xsd:boolean sh:report(report, name, sh, s, suc, vis){
    sh:report(report, sh:null, name, sh, sh:null, s, sh:null, sh:null, suc, vis)
}

function xsd:boolean sh:report(report, name, sh, s, p, o, suc, vis){
    sh:report(report, sh:null, name, sh, sh:null, s, p, o, suc, vis)
}

function xsd:boolean sh:report(report, name, sh, cst, s, p, o, suc, vis){
    sh:report(report, sh:null, name, sh, cst, s, p, o, suc, vis)
}

function xsd:boolean sh:report(report, subReport, name, sh, cst, s, p, o, suc, vis){
    sh:record(name,  sh, cst, sh:shaclGraph(), s, p, o, suc, vis);
    if (vis && ! suc) { 
        sh:visit(name, s, suc) ;
        return (sh:result(report, subReport, name, sh, cst, sh:shaclGraph(), s,  p, o)) ;
    } ;
    return(true)
}



#
# create validation result in report graph
# sh:  the shape
# cst: the constraint in case of sh:node
# foc: focus node
# node: value with problem 
#
function xsd:boolean sh:result(report, subReport, name, sh, cst, dt:graph shape, foc, path, node){
    let (res = uuid(),
        def = coalesce(sh:isdefby(name), name),
        sev = coalesce(xt:value(shape, sh, sh:severity), sh:Violation),
        mes = sh:getTheMessage(shape, sh, cst, foc, node),
        mesfun = sh:messageFunction(shape, sh, cst, foc, node),
        abnode = sh:bnodeid()) {

       sh:store(report, abnode, rdf:type, sh:ValidationReport);
       sh:store(report, abnode, sh:conforms, false);
       
       if (report = sh:validationReport()) {
            sh:store(report, abnode, sh:result, res);
            sh:store(report, res, rdf:type, sh:ValidationResult)      
       }
       else {
            sh:store(report, res, rdf:type, sh:AbstractResult)      
       } ;
              
       sh:store(report, res, sh:resultSeverity, sev);
       sh:store(report, res, sh:focusNode, foc);
       
       sh:store(report, res, sh:resultMessage, mes) ;
       if (coalesce(mesfun = "", false), true,  
            sh:store(report, res, sh:resultMessage2, mesfun)) ;
                        
       sh:store(report, res, sh:sourceConstraintComponent, def) ;
       sh:store(report, res, sh:sourceShape, sh) ;
                                              
       if (sh:isValue(path)) {
            sh:store(report, res, sh:resultPath, sh:prettyNodeOrList(shape, path))
       } ; 
       if (sh:isValue(node)) {
            sh:store(report, res, sh:value, node) 
       } ;
       
       if (isBlank(node)) {
            sh:store(report, res, sh:valueDetail, sh:graphdt(shape, node)) 
       } ;
       if (isBlank(foc) && ! sh:isFast()) {
            sh:store(report, res, sh:focusNodeDetail, sh:graphdt(shape, foc)) 
       };
       if (isBlank(sh)) {
            #sh:document(sh);
            coalesce(sh:store(report, res, sh:sourceShapeDetail, sh:getDefinition(sh)), true)
       };
       
       sh:resultFunction(report, subReport, res, sh, name, foc, path, node);

       return (res)

    } ;
    #return (true)
}






#
# Additional report
#
function sh:record(name,  sh, cst, dt:graph shape, foc, p, o, xsd:boolean suc, xsd:boolean vis) {
    if (vis) {
        sh:userreport(name,  sh, cst, shape, foc, p, o, suc);
        let (amap = sh:getrecordmap(name, suc)) {
            xt:set(amap, sh,          coalesce(xt:get(amap, sh), 0) + 1) ;
            xt:set(amap, sh:subtotal, coalesce(xt:get(amap, sh:subtotal), 0) + 1)  
        } ;
        let (bmap = sh:getrecordmap(sh:total, suc)) {
             xt:set(bmap, sh:total, coalesce(xt:get(bmap, sh:total), 0) + 1)
        }         
    } ;
    return(true)
}

function sh:userreport(name,  sh, cst, dt:graph shape, foc, p, o, xsd:boolean suc) {
    if (sh:hasSetup(sh:callback), 
        funcall(sh:setup(sh:callback), shape, sh, cst, name, foc, p, o, suc), 
        true) 
}

function sh:tracerecord(shape, mapmap) {
        for ((key val) in mapmap) {
            if (key != sh:def) {
                xt:print(key);
                for ((sh value) in val) {
                        xt:print(sh, ":", value) ;
                        if (isBlank(sh)) {
                            xt:print(xt:turtle(shape, sh))
                        }
                } ;
                xt:print("__")
            }
        } ;
        return (true)
}

# finish
function xsd:boolean sh:success(xsd:boolean bb) {
    if (bb) {
        let (g = 
            construct { [] a sh:ValidationReport ; sh:conforms true }
            where { }
            ) {
            sh:insert(g, sh:validationReport())
        }
    } ;
    return (true)
}

# insert report element g into report
function sh:insert(dt:graph g, dt:graph report) {
    for ((s p o) in g) {
        xt:insert(report, s, p, o)
    } 
}


function sh:store(gg, sub, pred, obj) {
    xt:insert(gg, sub, pred, obj)
}

function sh:insert(gg, sub, pred, obj) {
    xt:insert(gg, sub, pred, obj)
}

function sh:delete(gg, sub, pred, obj) {
    xt:delete(gg, sub, pred, obj)
}

function sh:myvalidationReport() {
    coalesce(tripleList, set(tripleList = xt:list()))
}



function sh:getTheMessage(shape, sh, cst, node, value) {
    sh:basicMessage(shape, sh, cst)
}

#
# when shape sh has xsh:messageFunction[ us:mess(param) ]
# return  funcall(us:mess, sh, node, value, param)
# use case: return contextual object in the neighborhood of node
#
function sh:messageFunction(shape, sh, cst, node, value) {
    let (mf = sh:getMessageExtension(sh)) {
        for ((oper name param) in mf) {
            let (res = funcall(name, sh, node, value, param)) {
                return (res)
            }
        }
    } ;
    return ("")
}

function sh:resultFunction(report, subReport, res, sh, oper, node, path, value) {
    let (rf = sh:getResultExtension(sh)) {
        if (xt:size(rf) = 0) {
            set (rf = sh:getResultExtensionGlobal(sh)) ;
            if (xt:size(rf) = 0 && sh:isValue(subReport)) {
                # there is no resultFunction and there is a subReport: default is merge
                sh:merge(report, subReport, res) ;
                return (res)
            }
        } ;
        for ((fun name param) in rf) {
            funcall(name, report, subReport, res, sh, oper, node, path, value, param)
        } 
    } ;
    return (res)
}

function sh:resultFunction2(report, subReport, res, sh, oper, node, path, value) {
    let (rf = sh:getResultExtension(sh)) {
        for ((fun name param) in rf) {
            funcall(name, report, subReport, res, sh, oper, node, path, value, param)
        } ;
        if (xt:size(rf) = 0 && sh:isValue(subReport)) {
            # there is no resultFunction but there is a subReport: default is merge
            sh:merge(report, subReport, res)
        }
    } 
}


# ((xsh:messageFunction name param))
function sh:getMessageExtension(sh) {
    sh:getShapeConstraint(sh:messageExtension, sh)
}


# ((xsh:messageFunction name param))
# sh:getFunctionExtension in constraint.rq
function sh:messageExtension(shape, sh) {
    sh:getFunctionExtension(shape, sh)
}

function sh:getResultExtension(sh) {
    sh:getShapeConstraint(sh:resultExtension, sh)
}


# ((xsh:resultFunction name param))
function sh:resultExtension(shape, sh) {
    sh:getResultExtension(shape, sh)
}


function sh:getResultExtensionGlobal(sh) {
    sh:getShapeConstraint(sh:resultExtensionGlobal, sh:resultExtensionGlobal)
}


# ((xsh:resultFunction name param))
function sh:resultExtensionGlobal(shape, sh) {
    sh:getResultExtensionGlobal(shape, sh)
}


function sh:basicMessage(shape, sh, cst) {
    coalesce (sh:getMessage(shape, sh, cst), 
              concat("Fail at: ", sh:createMessage(shape, sh, cst)))
}

function sh:createMessage(shape, sh, cst) {
    if (sh:isValue(cst), 
        xt:turtle(shape, cst),
        xt:turtle(shape, sh)  
    )
}

function sh:getMessage(shape, sh, cst) {
    if (sh:isValue(cst), 
        coalesce(xt:value(shape, cst, sh:message), xt:value(shape, sh, sh:message)),
        xt:value(shape, sh, sh:message)  
        )
}


function sh:tracefinish() {
    xt:print(xt:turtle(sh:validationReport()))
}

# when suc = false, declare error on node (for future pprint)
function sh:visit(name, node, suc) {
    st:visit(name, node, suc)
}

# within graph shape {}
function dt:uri sh:severity(sh) {
    coalesce(xt:value(sh, sh:severity), sh:Violation)
}

function sh:message(sh){
    xt:value(sh, sh:message)
}

function sh:bnodeid(){
    return(bnodeid) 
}




function sh:detailReport(report, detail) {
    if (detail, xt:create(dt:graph), report)
}



#
# Generate a validation result and join sub reports if any with sh:detail property
# sub reports are stored in subReport graph
#
function sh:reportDetail(report, subReport, oper, sh, s, p, o, suc, vis, detail) {
    sh:reportDetail(report, subReport, oper, sh, sh:null, s, p, o, suc, vis, detail)
}

function sh:reportDetail(report, subReport, oper, sh, cst, s, p, o, suc, vis, detail) {
    sh:report(report, if (detail && xt:size(subReport) > 0, subReport, sh:null),
        oper, sh, cst, s, p, o, suc, vis)
}


#
# url: url of current validation result 
# subReport : validation report of substatement (node, boolean)
# merge subReport in current report and 
# for each id in subReport, add triple: url sh:detail id
# TODO: delete sh:result triples from subReport
#
function sh:merge(report, subReport, url) {
    if (sh:isValue(subReport)) {
        letdyn (list = sh:collecturl(subReport), res = url, myreport = report) {
            xt:merge(report, subReport) ;
            map (function(id) { sh:store(myreport, res, sh:detail, id) }, list)
        }
    }
}

# return list of url of validation results
function sh:collecturl(report) {
    let (select ?report (aggregate(?url) as ?list) where { graph ?report { ?url a sh:AbstractResult } }) {
        return (list)
    }
}



function  sr:skipDetail(report, detail, url, shape, oper, s, p, o, exp) {

}

function sr:mergeDetail(report, detail, url, shape, oper, s, p, o, exp) {
    sh:merge(report, detail, url)
}













© 2015 - 2025 Weber Informatics LLC | Privacy Policy