org.apache.jena.shacl.validation.VR Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-shacl Show documentation
Show all versions of jena-shacl Show documentation
SHACL engine for Apache Jena
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.shacl.validation;
import java.util.HashSet;
import java.util.Set;
import org.apache.jena.atlas.lib.StrUtils;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.rdf.model.*;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.shacl.ValidationReport;
import org.apache.jena.shacl.engine.ShaclPaths;
import org.apache.jena.shacl.sys.C;
import org.apache.jena.shacl.vocabulary.SHACL;
import org.apache.jena.shacl.vocabulary.SHACLM;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.system.G;
import org.apache.jena.util.iterator.ExtendedIterator;
import org.apache.jena.vocabulary.RDF;
public class VR {
public static boolean compare(ValidationReport report1, ValidationReport report2) {
Model m1 = strip(report1.getResource().getModel());
Model m2 = strip(report2.getResource().getModel());
return m1.isIsomorphicWith(m2);
}
public static Model conformsModel() {
return ModelFactory.createDefaultModel().add(conformsModel);
}
private static Model conformsModel = ModelFactory.createDefaultModel();
static {
Resource report = conformsModel.createResource(SHACLM.ValidationReport);
report.addProperty(SHACLM.conforms, C.mTRUE);
}
public static void check(ValidationReport report) {
// Internal test.
// Also entries->model->entries but bnode, order issues.
Model m = report.getResource().getModel();
ValidationReport report2 = ValidationReport.fromModel(m);
Model m2 = report2.getResource().getModel();
boolean b = m.isIsomorphicWith(m2);
if ( ! b ) {
System.err.println("****");
RDFDataMgr.write(System.err, m, Lang.TTL);
System.err.println("++++ Round trip");
RDFDataMgr.write(System.err, m2, Lang.TTL);
System.err.println("----");
}
}
private static String PREFIXES = StrUtils.strjoinNL(
"PREFIX owl: ",
"PREFIX rdf: ",
"PREFIX rdfs: ",
"PREFIX sh: ",
"PREFIX xsd: ",
""
);
private static void prefixes(PrefixMapping pmap) {
pmap.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
pmap.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
pmap.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
pmap.setNsPrefix("sh", "http://www.w3.org/ns/shacl#");
pmap.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
}
// rdf:type sh:ValidationReport
// sh:result
// sh:conforms
// rdf:type sh:ValidationResult
// sh:focusNode
// sh:resultPath (including depending blank node structures)
// sh:resultSeverity
// sh:sourceConstraint
// sh:sourceConstraintComponent
// sh:sourceShape
// sh:value
private static String qs = StrUtils.strjoinNL
(PREFIXES,
"""
CONSTRUCT {
?X a sh:ValidationReport ;
sh:conforms ?conforms ;
sh:result ?R
.
?R sh:focusNode ?focusNode ;
sh:resultMessage ?message ;
sh:resultSeverity ?severity ;
sh:sourceConstraint ?constraint ;
sh:sourceConstraintComponent ?component ;
sh:sourceShape ?sourceShape ;
sh:resultPath ?path ;
sh:value ?value ;
.
}
WHERE {
?X a sh:ValidationReport ;
sh:result ?R
OPTIONAL { ?X sh:conforms ?conforms }
?R sh:focusNode ?focusNode ;
sh:resultSeverity ?severity ;
.
OPTIONAL { ?R sh:resultMessage ?message }
OPTIONAL { ?R sh:sourceConstraintComponent ?component }
OPTIONAL { ?R sh:sourceConstraint ?constraint }
OPTIONAL { ?R sh:sourceShape ?sourceShape }
OPTIONAL { ?R sh:resultPath ?path }
OPTIONAL { ?R sh:value ?value }
}
""");
private static Query query = QueryFactory.create(qs);
public static Model strip(Model model) {
ExtendedIterator iter = model.listStatements().filterKeep(stmt->keep(stmt));
Model m = ModelFactory.createDefaultModel();
iter.forEachRemaining(stmt->m.add(stmt));
prefixes(m);
Graph graph = model.getGraph();
Graph g = m.getGraph();
G.find(graph, null, SHACL.resultPath, null).toList().forEach(t->{
Node obj = t.getObject();
Node pn = ShaclPaths.copyPath(graph, g, obj);
g.add(Triple.create(t.getSubject(), t.getPredicate(), pn));
});
return m;
}
static Set properties = new HashSet<>();
static {
// Report
properties.add(SHACLM.result);
properties.add(SHACLM.conforms);
// Entries
properties.add(SHACLM.focusNode);
properties.add(SHACLM.resultSeverity);
properties.add(SHACLM.sourceConstraintComponent);
properties.add(SHACLM.value);
// Do specially. properties.add(SHACLM.resultPath);
// properties.add(SHACLM.sourceConstraint);
// properties.add(SHACLM.sourceShape);
}
private static boolean keep(Statement stmt) {
Property p = stmt.getPredicate();
if ( properties.contains(p))
return true;
return p.equals(RDF.type) && SHACLM.ValidationReport.equals(stmt.getObject());
}
}