ShaclSailBaseConfiguration.java
/*******************************************************************************
* Copyright (c) 2021 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.shacl;
import java.util.Set;
import org.eclipse.rdf4j.common.annotation.Experimental;
import org.eclipse.rdf4j.common.transaction.IsolationLevel;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.sail.NotifyingSail;
import org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper;
import org.eclipse.rdf4j.sail.inferencer.fc.SchemaCachingRDFSInferencer;
import org.eclipse.rdf4j.sail.shacl.config.ShaclSailConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
abstract class ShaclSailBaseConfiguration extends NotifyingSailWrapper {
private static final Logger logger = LoggerFactory.getLogger(ShaclSailBaseConfiguration.class);
// Field used to control if the new SPARQL based validation should be enabled or disabled. Enabled by default.
boolean sparqlValidation;
private boolean parallelValidation = ShaclSailConfig.PARALLEL_VALIDATION_DEFAULT;
private boolean logValidationPlans = ShaclSailConfig.LOG_VALIDATION_PLANS_DEFAULT;
private boolean logValidationViolations = ShaclSailConfig.LOG_VALIDATION_VIOLATIONS_DEFAULT;
private boolean validationEnabled = ShaclSailConfig.VALIDATION_ENABLED_DEFAULT;
private boolean cacheSelectNodes = ShaclSailConfig.CACHE_SELECT_NODES_DEFAULT;
private boolean rdfsSubClassReasoning = ShaclSailConfig.RDFS_SUB_CLASS_REASONING_DEFAULT;
private boolean serializableValidation = ShaclSailConfig.SERIALIZABLE_VALIDATION_DEFAULT;
private boolean performanceLogging = ShaclSailConfig.PERFORMANCE_LOGGING_DEFAULT;
private boolean eclipseRdf4jShaclExtensions = ShaclSailConfig.ECLIPSE_RDF4J_SHACL_EXTENSIONS_DEFAULT;
private boolean dashDataShapes = ShaclSailConfig.DASH_DATA_SHAPES_DEFAULT;
private long validationResultsLimitTotal = ShaclSailConfig.VALIDATION_RESULTS_LIMIT_TOTAL_DEFAULT;
private long validationResultsLimitPerConstraint = ShaclSailConfig.VALIDATION_RESULTS_LIMIT_PER_CONSTRAINT_DEFAULT;
private long transactionalValidationLimit = ShaclSailConfig.TRANSACTIONAL_VALIDATION_LIMIT_DEFAULT;
private boolean logValidationExecution = false;
private Set<IRI> shapesGraphs = ShaclSailConfig.SHAPES_GRAPHS_DEFAULT;
public ShaclSailBaseConfiguration(NotifyingSail baseSail) {
super(baseSail);
this.sparqlValidation = !"false"
.equalsIgnoreCase(System.getProperty("org.eclipse.rdf4j.sail.shacl.sparqlValidation"));
}
public ShaclSailBaseConfiguration() {
super();
this.sparqlValidation = !"false"
.equalsIgnoreCase(System.getProperty("org.eclipse.rdf4j.sail.shacl.sparqlValidation"));
}
/**
* Check if logging of every execution steps is enabled.
*
* @return <code>true</code> if enabled, <code>false</code> otherwise.
* @see #setGlobalLogValidationExecution(boolean)
*/
public boolean isGlobalLogValidationExecution() {
return logValidationExecution;
}
/**
* 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)
*
* @param loggingEnabled
*/
public void setGlobalLogValidationExecution(boolean loggingEnabled) {
logValidationExecution = loggingEnabled;
}
/**
* Check if logging a list of violations and the triples that caused the violations is enabled. It is recommended to
* disable parallel validation with {@link #setParallelValidation(boolean)}
*
* @see #setLogValidationViolations(boolean)
*/
public boolean isLogValidationViolations() {
return this.logValidationViolations;
}
/**
* Log (INFO) a list of violations and the triples that caused the violations (BETA). Recommended to disable
* parallel validation with setParallelValidation(false)
*
* @param logValidationViolations
*/
public void setLogValidationViolations(boolean logValidationViolations) {
this.logValidationViolations = logValidationViolations;
}
/**
* Check if SHACL validation is run in parellel.
*
* @return <code>true</code> if enabled, <code>false</code> otherwise.
*/
public boolean isParallelValidation() {
return this.parallelValidation;
}
/**
* EXPERIMENTAL! Run SHACL validation in parallel. Default: false
* <p>
* May cause deadlock, especially when using NativeStore.
*
* @param parallelValidation default true
*/
public void setParallelValidation(boolean parallelValidation) {
this.parallelValidation = parallelValidation;
}
/**
* Check if selected nodes caches is enabled.
*
* @return <code>true</code> if enabled, <code>false</code> otherwise.
* @see #setCacheSelectNodes(boolean)
*/
public boolean isCacheSelectNodes() {
return this.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
*
* @param cacheSelectNodes default true
*/
public void setCacheSelectNodes(boolean cacheSelectNodes) {
this.cacheSelectNodes = cacheSelectNodes;
}
public boolean isRdfsSubClassReasoning() {
return rdfsSubClassReasoning;
}
public void setRdfsSubClassReasoning(boolean rdfsSubClassReasoning) {
this.rdfsSubClassReasoning = rdfsSubClassReasoning;
}
/**
* Disable the SHACL validation on commit()
*/
public void disableValidation() {
this.validationEnabled = false;
}
/**
* Enabled the SHACL validation on commit()
*/
public void enableValidation() {
this.validationEnabled = true;
}
/**
* Check if SHACL validation on commit() is enabled.
*
* @return <code>true</code> if validation is enabled, <code>false</code> otherwise.
*/
public boolean isValidationEnabled() {
return validationEnabled;
}
/**
* Check if logging of validation plans is enabled.
*
* @return <code>true</code> if validation plan logging is enabled, <code>false</code> otherwise.
*/
public boolean isLogValidationPlans() {
return this.logValidationPlans;
}
/**
* Log (INFO) the executed validation plans as GraphViz DOT Recommended to disable parallel validation with
* setParallelValidation(false)
*
* @param logValidationPlans
*/
public void setLogValidationPlans(boolean logValidationPlans) {
this.logValidationPlans = logValidationPlans;
}
public boolean isPerformanceLogging() {
return performanceLogging;
}
// @formatter:off
/**
* Log (INFO) the execution time per shape. Recommended to disable the following:
* <ul>
* <li>setParallelValidation(false)</li>
* <li>setCacheSelectNodes(false)</li>
* </ul>
*
* @param performanceLogging default false
*/
// @formatter:on
public void setPerformanceLogging(boolean performanceLogging) {
this.performanceLogging = performanceLogging;
}
/**
* 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.
*
* @return <code>true</code> if serializable validation is enabled, <code>false</code> otherwise.
*/
public boolean isSerializableValidation() {
if (getBaseSail() instanceof SchemaCachingRDFSInferencer) {
if (serializableValidation) {
logger.warn("SchemaCachingRDFSInferencer is not supported when using serializable validation!");
}
return false;
}
return 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.
*
* <p>
* 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.
* </p>
*
* @param serializableValidation default true
*/
public void setSerializableValidation(boolean serializableValidation) {
this.serializableValidation = serializableValidation;
}
/**
* Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#). Enabling this currently enables
* support for rsx:targetShape.
* <p>
* EXPERIMENTAL!
*
* @return true if enabled
*/
@Experimental
public boolean isEclipseRdf4jShaclExtensions() {
return eclipseRdf4jShaclExtensions;
}
/**
* Support for Eclipse RDF4J SHACL Extensions (http://rdf4j.org/shacl-extensions#). Enabling this currently enables
* support for rsx:targetShape.
* <p>
* EXPERIMENTAL!
*
* @param eclipseRdf4jShaclExtensions true to enable (default: false)
*/
@Experimental
public void setEclipseRdf4jShaclExtensions(boolean eclipseRdf4jShaclExtensions) {
this.eclipseRdf4jShaclExtensions = eclipseRdf4jShaclExtensions;
}
/**
* Support for DASH Data Shapes Vocabulary Unofficial Draft (http://datashapes.org/dash). Currently this enables
* support for dash:hasValueIn, dash:AllObjectsTarget and dash:AllSubjectsTarget.
* <p>
* EXPERIMENTAL!
*
* @return true if enabled
*/
@Experimental
public boolean isDashDataShapes() {
return 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.
* <p>
* EXPERIMENTAL!
*
* @param dashDataShapes true to enable (default: false)
*/
@Experimental
public void setDashDataShapes(boolean dashDataShapes) {
this.dashDataShapes = dashDataShapes;
}
/**
* 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.
*
* @return the limit for validation results per validation report per constraint, -1 for no limit
*/
public long getValidationResultsLimitPerConstraint() {
return 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.
*
* @param validationResultsLimitPerConstraint the limit for the number of validation results per report per
* constraint, -1 for no limit
*/
public void setValidationResultsLimitPerConstraint(long validationResultsLimitPerConstraint) {
this.validationResultsLimitPerConstraint = validationResultsLimitPerConstraint;
}
/**
* @return the effective limit per constraint with an upper bound of the total limit
*/
public long getEffectiveValidationResultsLimitPerConstraint() {
if (validationResultsLimitPerConstraint < 0) {
return validationResultsLimitTotal;
}
if (validationResultsLimitTotal >= 0) {
return Math.min(validationResultsLimitTotal, validationResultsLimitPerConstraint);
}
return 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.
*
* @return the limit for validation results per validation report in total, -1 for no limit
*/
public long getValidationResultsLimitTotal() {
return 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.
*
* @param validationResultsLimitTotal the limit for the number of validation results per report in total, -1 for no
* limit
*/
public void setValidationResultsLimitTotal(long validationResultsLimitTotal) {
this.validationResultsLimitTotal = validationResultsLimitTotal;
}
@Override
public IsolationLevel getDefaultIsolationLevel() {
return super.getDefaultIsolationLevel();
}
public long getTransactionalValidationLimit() {
return transactionalValidationLimit;
}
public void setTransactionalValidationLimit(long transactionalValidationLimit) {
this.transactionalValidationLimit = transactionalValidationLimit;
}
public Set<IRI> getShapesGraphs() {
return shapesGraphs;
}
public void setShapesGraphs(Set<IRI> shapesGraphs) {
this.shapesGraphs = shapesGraphs;
}
}