Class ShaclSail

All Implemented Interfaces:
FederatedServiceResolverClient, NotifyingSail, Sail, StackableSail

public class ShaclSail extends ShaclSailBaseConfiguration
A Sail implementation that adds support for the Shapes Constraint Language (SHACL).

The ShaclSail looks for SHACL shape data in a special named graph RDF4J.SHACL_SHAPE_GRAPH.

Working example

import java.io.IOException;
import java.io.StringReader;

import org.eclipse.rdf4j.common.exception.ValidationException;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.vocabulary.RDF4J;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.WriterConfig;
import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;

public class ShaclSampleCode {

    public static void main(String[] args) throws IOException {

        ShaclSail shaclSail = new ShaclSail(new MemoryStore());

        SailRepository sailRepository = new SailRepository(shaclSail);
        sailRepository.init();

        try (SailRepositoryConnection connection = sailRepository.getConnection()) {

            connection.begin();

            StringReader shaclRules = new StringReader(String.join("\n", "",
                    "@prefix ex: <http://example.com/ns#> .",
                    "@prefix sh: <http://www.w3.org/ns/shacl#> .",
                    "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",
                    "@prefix foaf: <http://xmlns.com/foaf/0.1/>.",

                    "ex:PersonShape",
                    "    a sh:NodeShape  ;",
                    "    sh:targetClass foaf:Person ;",
                    "    sh:property ex:PersonShapeProperty .",

                    "ex:PersonShapeProperty ",
                    "    sh:path foaf:age ;",
                    "    sh:datatype xsd:int ;",
                    "    sh:maxCount 1 ;",
                    "    sh:minCount 1 ."
            ));

            connection.add(shaclRules, "", RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
            connection.commit();

            connection.begin();

            StringReader invalidSampleData = new StringReader(String.join("\n", "",
                    "@prefix ex: <http://example.com/ns#> .",
                    "@prefix foaf: <http://xmlns.com/foaf/0.1/>.",
                    "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",

                    "ex:peter a foaf:Person ;",
                    "    foaf:age 20, \"30\"^^xsd:int  ."

            ));

            connection.add(invalidSampleData, "", RDFFormat.TURTLE);
            try {
                connection.commit();
            } catch (RepositoryException exception) {
                Throwable cause = exception.getCause();
                if (cause instanceof ValidationException) {

                    // use the validationReportModel to understand validation violations
                    Model validationReportModel = ((ValidationException) cause).validationReportAsModel();

                    // Pretty print the validation report
                    WriterConfig writerConfig = new WriterConfig()
                            .set(BasicWriterSettings.PRETTY_PRINT, true)
                            .set(BasicWriterSettings.INLINE_BLANK_NODES, true);

                    Rio.write(validationReportModel, System.out, RDFFormat.TURTLE, writerConfig);
                    System.out.println();
                }

                throw exception;
            }
        }
    }
}
See Also: