TopQuadrant / shacl

SHACL API in Java based on Apache Jena
Apache License 2.0
217 stars 61 forks source link

Utilizing external JavaScript functions for constraint validation using SHACL-JS - SHACL API 1.3.2 #175

Closed AJAY31797 closed 4 months ago

AJAY31797 commented 4 months ago

I am trying to utilize SHACL-JS to access external JavaScript functions and perform constraint validation on an RDF graph. The reason for using external functions is I need to perform some complex mathematical operations, which cannot be performed directly within SHACL-SPARQL. The shape graph I used is as follows:

PREFIX CSRO: <http://www.semanticweb.org/aagr657/ontologies/2023/9/CraneSpaceRepresentationOntology#> 
PREFIX LinkOnt: <http://purl.org/ConstructLinkOnt/LinkOnt#> 
PREFIX bot: <https://w3id.org/bot#> 
PREFIX expr: <https://w3id.org/express#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geom: <http://rdf.bg/geometry.ttl#> 
PREFIX ifc: <https://standards.buildingsmart.org/IFC/DEV/IFC2x3/TC1/OWL#> 
PREFIX inst: <https://www.ugent.be/myAwesomeFirstBIMProject#> 
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX sf: <http://www.opengis.net/ont/sf#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX omg: <https://w3id.org/omg#> 
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX lbd: <https://linkedbuildingdata.org/LBD#>
PREFIX props: <http://lbd.arch.rwth-aachen.de/props#>
PREFIX unit: <http://qudt.org/vocab/unit/>
PREFIX IFC4-PSD: <https://www.linkedbuildingdata.net/IFC4-PSD#>
PREFIX smls: <https://w3id.org/def/smls-owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX fog: <https://w3id.org/fog#>
PREFIX vann: <http://purl.org/vocab/vann/>
PREFIX express: <https://w3id.org/express#>
PREFIX dce: <http://purl.org/dc/elements/1.1/>
PREFIX cc: <http://creativecommons.org/ns#>
PREFIX sh: <http://www.w3.org/ns/shacl#>

inst: 
     sh:declare [
     sh:prefix "inst";
     sh:namespace "https://www.ugent.be/myAwesomeFirstBIMProject#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "ifc";
     sh:namespace "https://standards.buildingsmart.org/IFC/DEV/IFC2x3/TC1/OWL#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "owl";
     sh:namespace "http://www.w3.org/2002/07/owl#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "LinkOnt";
     sh:namespace "http://purl.org/ConstructLinkOnt/LinkOnt#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "CSRO";
     sh:namespace "http://www.semanticweb.org/aagr657/ontologies/2023/9/CraneSpaceRepresentationOntology#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "expr";
     sh:namespace "https://w3id.org/express#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "bot";
     sh:namespace "https://w3id.org/bot#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "geo";
     sh:namespace "http://www.opengis.net/ont/geosparql#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "geom";
     sh:namespace "http://rdf.bg/geometry.ttl#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "sf";
     sh:namespace "http://www.opengis.net/ont/sf#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "xsd";
     sh:namespace "http://www.w3.org/2001/XMLSchema#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "omg";
     sh:namespace "https://w3id.org/omg#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "rdfs";
     sh:namespace "http://www.w3.org/2000/01/rdf-schema#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "lbd";
     sh:namespace "https://linkedbuildingdata.org/LBD#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "props";
     sh:namespace "http://lbd.arch.rwth-aachen.de/props#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "unit";
     sh:namespace "http://qudt.org/vocab/unit/"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "IFC4-PSD";
     sh:namespace "https://www.linkedbuildingdata.net/IFC4-PSD#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "smls";
     sh:namespace "https://w3id.org/def/smls-owl#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "rdf";
     sh:namespace "http://www.w3.org/1999/02/22-rdf-syntax-ns#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "fog";
     sh:namespace "https://w3id.org/fog#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "vann";
     sh:namespace "http://purl.org/vocab/vann/"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "dce";
     sh:namespace "http://purl.org/dc/elements/1.1/"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "cc";
     sh:namespace "http://creativecommons.org/ns#"^^xsd:anyURI ;
     ];
     sh:declare [
     sh:prefix "list";
     sh:namespace "https://w3id.org/list#"^^xsd:anyURI ;
     ].

inst:checkCollision
    rdf:type sh:JSFunction ;
    sh:parameter [
        sh:path inst:surface1;
        sh:datatype geo:wktLiteral;
    ];
    sh:parameter [
        sh:path inst:surface2;
        sh:datatype geo:wktLiteral;
    ];
    sh:returnType xsd:boolean;
    sh:jsLibrary [ sh:jsLibraryURL "http://localhost:8000/Constraint_Checking_Functions.js"^^xsd:anyURI ] ;
    sh:jsFunctionName "checkEQuality" .

inst:boundingBoxIntersectionDetection
    rdf:type sh:NodeShape ;
    sh:target [
            rdf:type sh:SPARQLTarget ; 
            sh:prefixes inst: ; 
            sh:select """
                SELECT $this
                WHERE {
                $this rdf:type ifc:IfcTask;
                      LinkOnt:TaskLevel LinkOnt:SubActivity.     
                }
            """;
        ];
    sh:sparql [
        rdf:type sh:SPARQLConstraint ;
        sh:message "Space constraint is violated for focus node: {$this}" ;
        sh:prefixes inst: ;
        sh:select"""
            SELECT $this
            WHERE {
                $this LinkOnt:HasResource ?resource.
                ?resource rdf:type LinkOnt:Resource;
                      LinkOnt:ResourceType LinkOnt:Equipment; 
                      owl:sameAs ?crane.
                ?crane rdf:type CSRO:CrawlerCrane;
                       CSRO:hasComponent ?craneComponent.
                ?craneComponent CSRO:hasBoundingBox ?polyhedralsurface1.
                ?polyhedralsurface1 rdf:type sf:PolyhedralSurface;
                           geo:asWKT ?surfaceValue1.
                ?siteElement rdf:type bot:Element;
                         CSRO:hasBoundingBox ?polyhedralsurface2.
                ?polyhedralsurface2 rdf:type sf:PolyhedralSurface;
                            geo:asWKT ?surfaceValue2.
                BIND (inst:checkCollision(?surfaceValue1, ?surfaceValue2) AS ?result).
                FILTER (?result = "true")
            }
            """;
        ].

This is a sample shape, which I am using just for testing purpose. The objective of this shape is just to validate that no two bounding boxes in the RDF data are different (as I said, this is just for testing purpose, just to get the approach right. I'll be developing shape and JS functions for more complex operations). The JS function checkEquality is as follows:

function checkEQuality ($surfaceValue1, $surfaceValue2) {
    if ($surfaceValue1 != $surfaceValue2) {
        return "true";
    }
}

The relevant sample data graph and the complete datagraph can be accessed using link (sample graph is just a smaller snippet of the complete RDF graph, containing relevant triples for testing) - https://drive.google.com/drive/folders/1onqLiqjmn2OLHDZj5Lqz8RVCxER7NED6?usp=sharing

For validation, I used TopQuadrant SHACL API 1.3.2, using the following command from command line:

shaclvalidate.bat -datafile "path to data graph" -shapesfile "path to shapes graph"

However, the validation result always comes to be true, as shown below:

@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix bot:   <https://w3id.org/bot#> .
@prefix dce:   <http://purl.org/dc/elements/1.1/> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix omg:   <https://w3id.org/omg#> .
@prefix express: <https://w3id.org/express#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix geom:  <http://rdf.bg/geometry.ttl#> .
@prefix geo:   <http://www.opengis.net/ont/geosparql#> .
@prefix sf:    <http://www.opengis.net/ont/sf#> .
@prefix smls:  <https://w3id.org/def/smls-owl#> .
@prefix expr:  <https://w3id.org/express#> .
@prefix vann:  <http://purl.org/vocab/vann/> .
@prefix cc:    <http://creativecommons.org/ns#> .
@prefix ifc:   <https://standards.buildingsmart.org/IFC/DEV/IFC2X3/TC1/OWL> .
@prefix list:  <https://w3id.org/list#> .
@prefix lbd:   <https://linkedbuildingdata.org/LBD#> .
@prefix props: <http://lbd.arch.rwth-aachen.de/props#> .
@prefix CSRO:  <http://www.semanticweb.org/aagr657/ontologies/2023/9/CraneSpaceRepresentationOntology#> .
@prefix unit:  <http://qudt.org/vocab/unit/> .
@prefix IFC4-PSD: <https://www.linkedbuildingdata.net/IFC4-PSD#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix inst:  <https://www.ugent.be/myAwesomeFirstBIMProject#> .
@prefix LinkOnt: <http://purl.org/ConstructLinkOnt/LinkOnt#> .
@prefix fog:   <https://w3id.org/fog#> .

[ a       <http://www.w3.org/ns/shacl#ValidationReport> ;
  <http://www.w3.org/ns/shacl#conforms>
          true
] .

The problem is that I am not sure if the shape is actually accessing the external function or not. This is because, for the FILTER statement in the SPARQL constraint, whatever value of the string I use in FILTER (?result = "true") in place of "true", the validation result is always true, which should not be the case. All the bounding boxes in the data graph are different, so this constraint should ideally be violated. I think there is something wrong with the way I am accessing the JS function and passing the arguments.

Could anyone please suggest if what I am trying is the right way of accessing the JavaScript functions from SHACL_JS and passing the arguments? What changes should be made to the shape so that I can pass the arguments to the external JS function and use the computation results for constraint checking? I searched a lot online, but not much of the information is available, other than the official W3C SHACL-JS documentation.

P.S. - I tried using pySHACL as well. Getting the same issue there as well.

Thanks a lot!

Best Regards, Ajay

ashleycaselli commented 4 months ago

Please see https://github.com/ashleycaselli/ajay-shacl-x-example