8.9 Validating RDF Data with SHACL Constraints

This section explains how to validate RDF graphs with SHACL (Shapes Constraint Language) constraints using Oracle RDF Graph Adapter for Eclipse RDF4J.

SHACL is a W3C standard for specifying constraints for RDF graphs. For example, SHACL allows you to specify that all instances of the ex:Person class must have a value for the ex:name property. SHACL defines an RDF vocabulary that allows you to specify constraints. An RDF graph that contains SHACL constraints is referred to as a shapes graph, and the RDF graph to be validated is referred to as a data graph.

RDF4J supports SHACL through its ShaclSail class. The SHACL engine in RDF4J validates a graph when changes to the graph are committed through RDF4J’s transaction mechanism. See the RDF4J Documentation for general information about RDF4J’s SHACL support.

When using ShaclSail with Oracle Adapter for Eclipse RDF4J through the OracleShaclSail class, a full SHACL validation runs when a transaction is committed. Incremental validation targeted at a subset of data is not supported. You should therefore avoid committing many small changes through an OracleShaclSail object, and use OracleShaclSail for large, bulk validation operations. The RDF4J SHACL engine sends a series of SPARQL queries to Oracle Database to check for constraint violations. A typical workflow for bulk validation is shown below:

  1. Create an OracleSailStore object for an RDF data graph stored in Oracle Database.
  2. Create an OracleShaclSail object that wraps the OracleSailStore.
  3. Create a SailRepository from the OracleShaclSail object.
  4. Begin a transaction on the SailRepository.
  5. Add a shapes graph to the RDF4J.SHACL_SHAPE_GRAPH context as a part of the transaction (this shapes graph can be loaded from a variety of sources).
  6. Commit the transaction.
  7. A RepositoryException will be raised if a constraint is violated.
  8. Check the validation report if an exception was raised.

These steps are illustrated in the following code fragment:

// Get an OracleSailStore instance for the stored data graph to validate
OraclePool op = new OraclePool(jdbcURL, user, password);
NotifyingSail store = new OracleSailStore(op, "DATA_GRAPH", "SCOTT", "NET1");

// Create an OracleShaclSail on top of the underlying OracleSailStore
ShaclSail shaclSail = new OracleShaclSail(store);
SailRepository sailRepository = new SailRepository(shaclSail);
sailRepository.init();

// Get a connection from the repository, start a transaction,
// load a shapes graph and commit the transaction to validate the data graph
try (SailRepositoryConnection conn = sailRepository.getConnection()) {
  conn.begin();
  // clear any existing shapes graph
  conn.clear(RDF4J.SHACL_SHAPE_GRAPH);
  // Add current shapes graph
  // Every person must have a name property
  StringReader shaclRules = new StringReader(
    String.join(
      "\n", "",
      "@prefix ex: <http://oracle.example.com/ns#> .",
      "@prefix sh: <http://www.w3.org/ns/shacl#> .",
      "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .",
      "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .",
      "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .",

      "ex:MinCountShape",
      "  a sh:NodeShape ;",
      "  sh:targetClass ex:Person ;",
      "  sh:property [",
      "    sh:path ex:name ;",
      "    sh:minCount 1 ;",
      "  ] ."
    )
  );

  try {
    conn.add(shaclRules, null, RDFFormat.TURTLE, RDF4J.SHACL_SHAPE_GRAPH);
  }
  catch (IOException e) {
    e.printStackTrace();
  }

  // Commit transaction to validate the data graph with the current shapes graph
  try {
    conn.commit();
  }
  catch (RepositoryException e) {
    Throwable cause = e.getCause();
    if (cause instanceof ValidationException) {
      Model validationReportModel = ((ValidationException) cause).validationReportAsModel();

      WriterConfig writerConfig = new WriterConfig()
        .set(BasicWriterSettings.INLINE_BLANK_NODES, true)
        .set(BasicWriterSettings.XSD_STRING_TO_PLAIN_LITERAL, true)
        .set(BasicWriterSettings.PRETTY_PRINT, true);

      Rio.write(validationReportModel, System.out, RDFFormat.TURTLE, writerConfig);
    }
    else {
      e.printStackTrace();
    }
  }
}

8.9.1 SHACL Features Supported by Oracle Adapter for Eclipse RDF4J

This section lists the SHACL core constraints supported by Oracle Adapter for Eclipse RDF4J.

  • http://www.w3.org/ns/shacl#alternativePath
  • http://www.w3.org/ns/shacl#class
  • http://www.w3.org/ns/shacl#datatype
  • http://www.w3.org/ns/shacl#deactivated
  • http://www.w3.org/ns/shacl#flags
  • http://www.w3.org/ns/shacl#hasValue
  • http://www.w3.org/ns/shacl#in
  • http://www.w3.org/ns/shacl#inversePath
  • http://www.w3.org/ns/shacl#languageIn
  • http://www.w3.org/ns/shacl#maxCount
  • http://www.w3.org/ns/shacl#maxExclusive
  • http://www.w3.org/ns/shacl#maxInclusive
  • http://www.w3.org/ns/shacl#maxLength
  • http://www.w3.org/ns/shacl#minCount
  • http://www.w3.org/ns/shacl#minExclusive
  • http://www.w3.org/ns/shacl#minInclusive
  • http://www.w3.org/ns/shacl#minLength
  • http://www.w3.org/ns/shacl#node
  • http://www.w3.org/ns/shacl#nodeKind
  • http://www.w3.org/ns/shacl#path
  • http://www.w3.org/ns/shacl#pattern
  • http://www.w3.org/ns/shacl#property
  • http://www.w3.org/ns/shacl#severity
  • http://www.w3.org/ns/shacl#target
  • http://www.w3.org/ns/shacl#targetClass
  • http://www.w3.org/ns/shacl#targetNode
  • http://www.w3.org/ns/shacl#targetObjectsOf
  • http://www.w3.org/ns/shacl#targetSubjectsOf
  • http://www.w3.org/ns/shacl#uniqueLang
The following features are not enabled by default but can be enabled by setting the system property oracle.rdf4j.adapter.restrictShaclFeatures to the value F. These features should only be used with smaller RDF datasets because the RDF4J SHACL engine’s implementation reads the set of target nodes into the client program’s memory when evaluating constraints with these features.
  • http://www.w3.org/ns/shacl#and
  • http://www.w3.org/ns/shacl#not
  • http://www.w3.org/ns/shacl#or
  • http://www.w3.org/ns/shacl#qualifiedMaxCount
  • http://www.w3.org/ns/shacl#qualifiedMinCount
  • http://www.w3.org/ns/shacl#qualifiedValueShape
  • http://www.w3.org/ns/shacl#sparql

8.9.2 Restrictions on the use of RDF4J SHACL Features

This section describes the restrictions on the use of RDF4J SHACL features.

Oracle Adapter for Eclipse RDF4J only supports SHACL Shapes stored in the reserved named graph (context) http://rdf4j.org/schema/rdf4j#SHACLShapeGraph. In general, ShaclSail allows you to load shapes graphs from arbitrary named graphs identified with the setShapesGraph method. However, setShapesGraph is not supported by Oracle Adapter for Eclipse RDF4J.