Package org.eclipse.rdf4j.sail.shacl

## Class ShaclSail

- java.lang.Object
- - org.eclipse.rdf4j.sail.helpers.SailWrapper
  - - org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper
    - - org.eclipse.rdf4j.sail.shacl.ShaclSail

- All Implemented Interfaces:
    `FederatedServiceResolverClient`, `NotifyingSail`, `Sail`, `StackableSail`

      public class ShaclSail
      extends NotifyingSailWrapper

  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;
                   }
               }
           }
       }

  Author:
    Heshan Jayasinghe, Håvard Ottestad
  See Also:
    SHACL W3C Recommendation

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class | Description
    --- | --- | ---
    `protected static class` | `ShaclSail.RevivableExecutorService` |
    `static class` | `ShaclSail.TransactionSettings` |

  - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---
    `ShaclSail()` |
    `ShaclSail​(NotifyingSail baseSail)` |

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `disableValidation()` | Disable the SHACL validation on commit()
    `void` | `enableValidation()` | Enabled the SHACL validation on commit()
    `StampedLockManager.Cache.ReadableState` | `getCachedShapes()` |
    `NotifyingSailConnection` | `getConnection()` | Opens a connection on the Sail which can be used to query and update data.
    `IsolationLevel` | `getDefaultIsolationLevel()` | Retrieves the default `IsolationLevel` level on which transactions in this Sail operate.
    `long` | `getEffectiveValidationResultsLimitPerConstraint()` |
    `protected ShaclSail.RevivableExecutorService` | `getExecutorService()` |
    `List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes>` | `getShapes​(IRI[] shapesGraphs, boolean onlyRdf4jShaclShapeGraph)` |
    `List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes>` | `getShapes​(RepositoryConnection shapesRepoConnection, IRI[] shapesGraphs)` |
    `List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes>` | `getShapes​(RepositoryConnection shapesRepoConnection, SailConnection sailConnection, IRI[] shapesGraphs)` |
    `Set<IRI>` | `getShapesGraphs()` |
    `static List<IRI>` | `getSupportedShaclPredicates()` | Lists the predicates that have been implemented in the ShaclSail.
    `long` | `getTransactionalValidationLimit()` |
    `long` | `getValidationResultsLimitPerConstraint()` | ValidationReports contain validation results.
    `long` | `getValidationResultsLimitTotal()` | ValidationReports contain validation results.
    `void` | `init()` | Initializes the Sail.
    `boolean` | `isCacheSelectNodes()` | Check if selected nodes caches is enabled.
    `boolean` | `isDashDataShapes()` | Support for DASH Data Shapes Vocabulary Unofficial Draft (http://datashapes.org/dash).
    `boolean` | `isEclipseRdf4jShaclExtensions()` | Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#).
    `boolean` | `isGlobalLogValidationExecution()` | Check if logging of every execution steps is enabled.
    `boolean` | `isLogValidationPlans()` | Check if logging of validation plans is enabled.
    `boolean` | `isLogValidationViolations()` | Check if logging a list of violations and the triples that caused the violations is enabled.
    `boolean` | `isParallelValidation()` | Check if SHACL validation is run in parellel.
    `boolean` | `isPerformanceLogging()` |
    `boolean` | `isRdfsSubClassReasoning()` |
    `boolean` | `isSerializableValidation()` | On transactions using SNAPSHOT isolation the ShaclSail can run the validation serializably.
    `boolean` | `isValidationEnabled()` | Check if SHACL validation on commit() is enabled.
    `void` | `setBaseSail​(Sail baseSail)` | Sets the base Sail that this Sail will work on top of.
    `void` | `setCacheSelectNodes​(boolean cacheSelectNodes)` | The ShaclSail retries a lot of its relevant data through running SPARQL Select queries against the underlying sail and against the changes in the transaction.
    `void` | `setDashDataShapes​(boolean dashDataShapes)` | Support for DASH Data Shapes Vocabulary Unofficial Draft (http://datashapes.org/dash).
    `void` | `setEclipseRdf4jShaclExtensions​(boolean eclipseRdf4jShaclExtensions)` | Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#).
    `void` | `setGlobalLogValidationExecution​(boolean loggingEnabled)` | Log (INFO) every execution step of the SHACL validation.
    `void` | `setLogValidationPlans​(boolean logValidationPlans)` | Log (INFO) the executed validation plans as GraphViz DOT Recommended to disable parallel validation with setParallelValidation(false)
    `void` | `setLogValidationViolations​(boolean logValidationViolations)` | Log (INFO) a list of violations and the triples that caused the violations (BETA).
    `void` | `setParallelValidation​(boolean parallelValidation)` | EXPERIMENTAL! Run SHACL validation in parallel.
    `void` | `setPerformanceLogging​(boolean performanceLogging)` | Log (INFO) the execution time per shape.
    `void` | `setRdfsSubClassReasoning​(boolean rdfsSubClassReasoning)` |
    `void` | `setSerializableValidation​(boolean serializableValidation)` | Enable or disable serializable validation.On transactions using SNAPSHOT isolation the ShaclSail can run the validation serializably.
    `void` | `setShapesGraphs​(Set<IRI> shapesGraphs)` |
    `void` | `setTransactionalValidationLimit​(long transactionalValidationLimit)` |
    `void` | `setValidationResultsLimitPerConstraint​(long validationResultsLimitPerConstraint)` | ValidationReports contain validation results.
    `void` | `setValidationResultsLimitTotal​(long validationResultsLimitTotal)` | ValidationReports contain validation results.
    `void` | `shutDown()` | Shuts down the Sail, giving it the opportunity to synchronize any stale data.

    - ### Methods inherited from class org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper

      `addSailChangedListener, getBaseSail, removeSailChangedListener`

    - ### Methods inherited from class org.eclipse.rdf4j.sail.helpers.SailWrapper

      `getDataDir, getSupportedIsolationLevels, getValueFactory, isWritable, setDataDir, setFederatedServiceResolver, verifyBaseSailSet`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

    - ### Methods inherited from interface org.eclipse.rdf4j.sail.Sail

      `getDataDir, getSupportedIsolationLevels, getValueFactory, isWritable, setDataDir`

- - ### Constructor Detail

    - #### ShaclSail

          public ShaclSail​(NotifyingSail baseSail)

    - #### ShaclSail

          public ShaclSail()

  - ### Method Detail

    - #### getCachedShapes

          @InternalUseOnly
          public StampedLockManager.Cache.ReadableState getCachedShapes()
                                                                 throws InterruptedException

      Throws:
        `InterruptedException`

    - #### setBaseSail

          public void setBaseSail​(Sail baseSail)

      Description copied from interface: `StackableSail`
      Sets the base Sail that this Sail will work on top of. This method will be called before the initialize() method is called.
      Specified by:
        `setBaseSail` in interface `StackableSail`
      Overrides:
        `setBaseSail` in class `NotifyingSailWrapper`

    - #### getExecutorService

          @Experimental
          protected ShaclSail.RevivableExecutorService getExecutorService()

      Returns:

    - #### getSupportedShaclPredicates

          public static List<IRI> getSupportedShaclPredicates()

      Lists the predicates that have been implemented in the ShaclSail. All of these, and all combinations, should work, please report any bugs. For sh:path, only single predicate paths, or single predicate inverse paths are supported. DASH and RSX features may need to be enabled.
      Returns:
        List of IRIs (SHACL predicates)

    - #### init

          public void init()
                    throws SailException

      Description copied from interface: `Sail`
      Initializes the Sail. Care should be taken that required initialization parameters have been set before this method is called. Please consult the specific Sail implementation for information about the relevant parameters.
      Specified by:
        `init` in interface `Sail`
      Overrides:
        `init` in class `SailWrapper`
      Throws:
        `SailException` - If the Sail could not be initialized.

    - #### getShapes

          @InternalUseOnly
          public List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes> getShapes​(RepositoryConnection shapesRepoConnection,
                                                                                    SailConnection sailConnection,
                                                                                    IRI[] shapesGraphs)
                                                                             throws SailException

      Throws:
        `SailException`

    - #### getShapes

          @InternalUseOnly
          public List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes> getShapes​(RepositoryConnection shapesRepoConnection,
                                                                                    IRI[] shapesGraphs)
                                                                             throws SailException

      Throws:
        `SailException`

    - #### shutDown

          public void shutDown()
                        throws SailException

      Description copied from interface: `Sail`
      Shuts down the Sail, giving it the opportunity to synchronize any stale data. Care should be taken that all initialized Sails are being shut down before an application exits to avoid potential loss of data. Once shut down, a Sail can no longer be used until it is re-initialized.
      Specified by:
        `shutDown` in interface `Sail`
      Overrides:
        `shutDown` in class `SailWrapper`
      Throws:
        `SailException` - If the Sail object encountered an error or unexpected situation internally.

    - #### getConnection

          public NotifyingSailConnection getConnection()
                                                throws SailException

      Description copied from interface: `Sail`
      Opens a connection on the Sail which can be used to query and update data. Depending on how the implementation handles concurrent access, a call to this method might block when there is another open connection on this Sail.
      Specified by:
        `getConnection` in interface `NotifyingSail`
      Specified by:
        `getConnection` in interface `Sail`
      Overrides:
        `getConnection` in class `NotifyingSailWrapper`
      Throws:
        `SailException` - If no transaction could be started, for example because the Sail is not writable.

    - #### getShapes

          @InternalUseOnly
          public List<org.eclipse.rdf4j.sail.shacl.ast.ContextWithShapes> getShapes​(IRI[] shapesGraphs,
                                                                                    boolean onlyRdf4jShaclShapeGraph)

    - #### setShapesGraphs

          public void setShapesGraphs​(Set<IRI> shapesGraphs)

    - #### isSerializableValidation

          public boolean isSerializableValidation()

      On transactions using SNAPSHOT isolation the ShaclSail can run the validation serializably. This stops the sail from becoming inconsistent due to race conditions between two transactions. Serializable validation limits TPS (transactions per second), it is however considerably faster than actually using SERIALIZABLE isolation.
      Returns:
        `true` if serializable validation is enabled, `false` otherwise.

    - #### isGlobalLogValidationExecution

          public boolean isGlobalLogValidationExecution()

      Check if logging of every execution steps is enabled.
      Returns:
        `true` if enabled, `false` otherwise.
      See Also:
        `setGlobalLogValidationExecution(boolean)`

    - #### setGlobalLogValidationExecution

          public void setGlobalLogValidationExecution​(boolean loggingEnabled)

      Log (INFO) every execution step of the SHACL validation. This is fairly costly and should not be used in production. Recommended to disable parallel validation with setParallelValidation(false)
      Parameters:
        `loggingEnabled` -

    - #### isLogValidationViolations

          public boolean isLogValidationViolations()

      Check if logging a list of violations and the triples that caused the violations is enabled. It is recommended to disable parallel validation with `setParallelValidation(boolean)`
      See Also:
        `setLogValidationViolations(boolean)`

    - #### setLogValidationViolations

          public void setLogValidationViolations​(boolean logValidationViolations)

      Log (INFO) a list of violations and the triples that caused the violations (BETA). Recommended to disable parallel validation with setParallelValidation(false)
      Parameters:
        `logValidationViolations` -

    - #### isParallelValidation

          public boolean isParallelValidation()

      Check if SHACL validation is run in parellel.
      Returns:
        `true` if enabled, `false` otherwise.

    - #### setParallelValidation

          public void setParallelValidation​(boolean parallelValidation)

      EXPERIMENTAL! Run SHACL validation in parallel. Default: false

      May cause deadlock, especially when using NativeStore.

      Parameters:
        `parallelValidation` - default true

    - #### isCacheSelectNodes

          public boolean isCacheSelectNodes()

      Check if selected nodes caches is enabled.
      Returns:
        `true` if enabled, `false` otherwise.
      See Also:
        `setCacheSelectNodes(boolean)`

    - #### setCacheSelectNodes

          public void setCacheSelectNodes​(boolean cacheSelectNodes)

      The ShaclSail retries a lot of its relevant data through running SPARQL Select queries against the underlying sail and against the changes in the transaction. This is usually good for performance, but while validating large amounts of data disabling this cache will use less memory. Default: true
      Parameters:
        `cacheSelectNodes` - default true

    - #### isRdfsSubClassReasoning

          public boolean isRdfsSubClassReasoning()

    - #### setRdfsSubClassReasoning

          public void setRdfsSubClassReasoning​(boolean rdfsSubClassReasoning)

    - #### disableValidation

          public void disableValidation()

      Disable the SHACL validation on commit()

    - #### enableValidation

          public void enableValidation()

      Enabled the SHACL validation on commit()

    - #### isValidationEnabled

          public boolean isValidationEnabled()

      Check if SHACL validation on commit() is enabled.
      Returns:
        `true` if validation is enabled, `false` otherwise.

    - #### isLogValidationPlans

          public boolean isLogValidationPlans()

      Check if logging of validation plans is enabled.
      Returns:
        `true` if validation plan logging is enabled, `false` otherwise.

    - #### setLogValidationPlans

          public void setLogValidationPlans​(boolean logValidationPlans)

      Log (INFO) the executed validation plans as GraphViz DOT Recommended to disable parallel validation with setParallelValidation(false)
      Parameters:
        `logValidationPlans` -

    - #### isPerformanceLogging

          public boolean isPerformanceLogging()

    - #### setPerformanceLogging

          public void setPerformanceLogging​(boolean performanceLogging)

      Log (INFO) the execution time per shape. Recommended to disable the following:
      - setParallelValidation(false)
      - setCacheSelectNodes(false)
      Parameters:
        `performanceLogging` - default false

    - #### setSerializableValidation

          public void setSerializableValidation​(boolean serializableValidation)

      Enable or disable serializable validation.On transactions using SNAPSHOT isolation the ShaclSail can run the validation serializably. This stops the sail from becoming inconsistent due to race conditions between two transactions. Serializable validation limits TPS (transactions per second), it is however considerably faster than actually using SERIALIZABLE isolation.

      To increase TPS, serializable validation can be disabled. Validation will then be limited to the semantics of the SNAPSHOT isolation level (or whichever is specified). If you use any other isolation level than SNAPSHOT, disabling serializable validation will make no difference on performance.

      Parameters:
        `serializableValidation` - default true

    - #### isEclipseRdf4jShaclExtensions

          @Experimental
          public boolean isEclipseRdf4jShaclExtensions()

      Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#). Enabling this currently enables support for rsx:targetShape. EXPERIMENTAL!
      Returns:
        true if enabled

    - #### setEclipseRdf4jShaclExtensions

          @Experimental
          public void setEclipseRdf4jShaclExtensions​(boolean eclipseRdf4jShaclExtensions)

      Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#). Enabling this currently enables support for rsx:targetShape. EXPERIMENTAL!
      Parameters:
        `eclipseRdf4jShaclExtensions` - true to enable (default: false)

    - #### isDashDataShapes

          @Experimental
          public boolean isDashDataShapes()

      Support for DASH Data Shapes Vocabulary Unofficial Draft (http://datashapes.org/dash). Currently this enables support for dash:hasValueIn, dash:AllObjectsTarget and dash:AllSubjectsTarget. EXPERIMENTAL!
      Returns:
        true if enabled

    - #### setDashDataShapes

          @Experimental
          public void setDashDataShapes​(boolean dashDataShapes)

      Support for DASH Data Shapes Vocabulary Unofficial Draft (http://datashapes.org/dash). Currently this enables support for dash:hasValueIn, dash:AllObjectsTarget and and dash:AllSubjectsTarget. EXPERIMENTAL!
      Parameters:
        `dashDataShapes` - true to enable (default: false)

    - #### getValidationResultsLimitPerConstraint

          public long getValidationResultsLimitPerConstraint()

      ValidationReports contain validation results. The number of validation results can be limited by the user. This can be useful to reduce the size of reports when there are a lot of failures, which increases validation speed and reduces memory usage.
      Returns:
        the limit for validation results per validation report per constraint, -1 for no limit

    - #### setValidationResultsLimitPerConstraint

          public void setValidationResultsLimitPerConstraint​(long validationResultsLimitPerConstraint)

      ValidationReports contain validation results. The number of validation results can be limited by the user. This can be useful to reduce the size of reports when there are a lot of failures, which increases validation speed and reduces memory usage.
      Parameters:
        `validationResultsLimitPerConstraint` - the limit for the number of validation results per report per constraint, -1 for no limit

    - #### getEffectiveValidationResultsLimitPerConstraint

          public long getEffectiveValidationResultsLimitPerConstraint()

      Returns:
        the effective limit per constraint with an upper bound of the total limit

    - #### getValidationResultsLimitTotal

          public long getValidationResultsLimitTotal()

      ValidationReports contain validation results. The number of validation results can be limited by the user. This can be useful to reduce the size of reports when there are a lot of failures, which increases validation speed and reduces memory usage.
      Returns:
        the limit for validation results per validation report in total, -1 for no limit

    - #### setValidationResultsLimitTotal

          public void setValidationResultsLimitTotal​(long validationResultsLimitTotal)

      ValidationReports contain validation results. The number of validation results can be limited by the user. This can be useful to reduce the size of reports when there are a lot of failures, which increases validation speed and reduces memory usage.
      Parameters:
        `validationResultsLimitTotal` - the limit for the number of validation results per report in total, -1 for no limit

    - #### getDefaultIsolationLevel

          public IsolationLevel getDefaultIsolationLevel()

      Description copied from interface: `Sail`
      Retrieves the default `IsolationLevel` level on which transactions in this Sail operate.
      Specified by:
        `getDefaultIsolationLevel` in interface `Sail`
      Overrides:
        `getDefaultIsolationLevel` in class `SailWrapper`
      Returns:
        the `IsolationLevel` that will be used with `SailConnection.begin()`, for SAIL connections returned by `Sail.getConnection()`.

    - #### getTransactionalValidationLimit

          public long getTransactionalValidationLimit()

    - #### setTransactionalValidationLimit

          public void setTransactionalValidationLimit​(long transactionalValidationLimit)

    - #### getShapesGraphs

          public Set<IRI> getShapesGraphs()