diff --git a/assembly-descriptors/pom.xml b/assembly-descriptors/pom.xml index 837f7647d0a..adb16157dc8 100644 --- a/assembly-descriptors/pom.xml +++ b/assembly-descriptors/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-assembly-descriptors RDF4J: Assembly Descriptors diff --git a/assembly/pom.xml b/assembly/pom.xml index c5decadbbda..a88d567f0e5 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-assembly pom diff --git a/bom/pom.xml b/bom/pom.xml index e7312671ab1..f9a2a634d30 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-bom pom diff --git a/compliance/elasticsearch/pom.xml b/compliance/elasticsearch/pom.xml index 4684d29c437..794dacb7bd7 100644 --- a/compliance/elasticsearch/pom.xml +++ b/compliance/elasticsearch/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-elasticsearch-compliance RDF4J: Elasticsearch Sail Tests diff --git a/compliance/geosparql/pom.xml b/compliance/geosparql/pom.xml index ee4e8c2e02e..41e8785595b 100644 --- a/compliance/geosparql/pom.xml +++ b/compliance/geosparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-geosparql-compliance RDF4J: GeoSPARQL compliance tests diff --git a/compliance/lucene/pom.xml b/compliance/lucene/pom.xml index 2afc2a34c99..dcf84054c6d 100644 --- a/compliance/lucene/pom.xml +++ b/compliance/lucene/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-lucene-compliance RDF4J: Lucene Sail Tests diff --git a/compliance/model/pom.xml b/compliance/model/pom.xml index 43745d0d22a..3d3ac105fa9 100644 --- a/compliance/model/pom.xml +++ b/compliance/model/pom.xml @@ -3,7 +3,7 @@ rdf4j-compliance org.eclipse.rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT 4.0.0 rdf4j-model-compliance diff --git a/compliance/pom.xml b/compliance/pom.xml index 25bb1a984f3..7a3f7a3e7ff 100644 --- a/compliance/pom.xml +++ b/compliance/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-compliance pom diff --git a/compliance/repository/pom.xml b/compliance/repository/pom.xml index 4d1642cc9e9..069ade53eec 100644 --- a/compliance/repository/pom.xml +++ b/compliance/repository/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-compliance war diff --git a/compliance/rio/pom.xml b/compliance/rio/pom.xml index b2d22802dc6..850062bf2f4 100644 --- a/compliance/rio/pom.xml +++ b/compliance/rio/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-compliance RDF4J: Rio compliance tests diff --git a/compliance/solr/pom.xml b/compliance/solr/pom.xml index 2bb8b044e0a..454f5295ca6 100644 --- a/compliance/solr/pom.xml +++ b/compliance/solr/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-solr-compliance RDF4J: Solr Sail Tests diff --git a/compliance/sparql/pom.xml b/compliance/sparql/pom.xml index 4f85a0c09e1..3340661c18d 100644 --- a/compliance/sparql/pom.xml +++ b/compliance/sparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-compliance - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sparql-compliance war diff --git a/core/client/pom.xml b/core/client/pom.xml index 7cc1c61cf91..845360a26cc 100644 --- a/core/client/pom.xml +++ b/core/client/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-client RDF4J: Client Libraries diff --git a/core/collection-factory/api/pom.xml b/core/collection-factory/api/pom.xml index be1452b7514..5ba6df646b7 100644 --- a/core/collection-factory/api/pom.xml +++ b/core/collection-factory/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-collection-factory - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-collection-factory-api RDF4J: Collection Factory - API diff --git a/core/collection-factory/mapdb/pom.xml b/core/collection-factory/mapdb/pom.xml index 837789ddc5f..c8e843b984e 100644 --- a/core/collection-factory/mapdb/pom.xml +++ b/core/collection-factory/mapdb/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-collection-factory - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-collection-factory-mapdb RDF4J: Collection Factory - Map DB backed diff --git a/core/collection-factory/mapdb3/pom.xml b/core/collection-factory/mapdb3/pom.xml index bbfc353aa78..a00d4c8e811 100644 --- a/core/collection-factory/mapdb3/pom.xml +++ b/core/collection-factory/mapdb3/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-collection-factory - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-collection-factory-mapdb3 RDF4J: Collection Factory - Map DB v3 backed diff --git a/core/collection-factory/pom.xml b/core/collection-factory/pom.xml index 631395e0738..bb1df7bb226 100644 --- a/core/collection-factory/pom.xml +++ b/core/collection-factory/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-collection-factory pom diff --git a/core/common/annotation/pom.xml b/core/common/annotation/pom.xml index 299ec3569a1..f5f53a65e21 100644 --- a/core/common/annotation/pom.xml +++ b/core/common/annotation/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-annotation RDF4J: common annotation diff --git a/core/common/exception/pom.xml b/core/common/exception/pom.xml index 787f801ecbc..bbd533f1adf 100644 --- a/core/common/exception/pom.xml +++ b/core/common/exception/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-exception RDF4J: common exception diff --git a/core/common/io/pom.xml b/core/common/io/pom.xml index 803ea846d0f..f99f7f2af4e 100644 --- a/core/common/io/pom.xml +++ b/core/common/io/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-io RDF4J: common IO diff --git a/core/common/iterator/pom.xml b/core/common/iterator/pom.xml index 5d3118ee786..c8b62012574 100644 --- a/core/common/iterator/pom.xml +++ b/core/common/iterator/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-iterator RDF4J: common iterators diff --git a/core/common/order/pom.xml b/core/common/order/pom.xml index 1acbf8a8a81..5228081fc0e 100644 --- a/core/common/order/pom.xml +++ b/core/common/order/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-order RDF4J: common order diff --git a/core/common/pom.xml b/core/common/pom.xml index 95b37fd0f42..fc821867500 100644 --- a/core/common/pom.xml +++ b/core/common/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common pom diff --git a/core/common/text/pom.xml b/core/common/text/pom.xml index 7f0232992b9..f26391a3d11 100644 --- a/core/common/text/pom.xml +++ b/core/common/text/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-text RDF4J: common text diff --git a/core/common/transaction/pom.xml b/core/common/transaction/pom.xml index d4d272e46c0..2a327eba54c 100644 --- a/core/common/transaction/pom.xml +++ b/core/common/transaction/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-transaction RDF4J: common transaction diff --git a/core/common/xml/pom.xml b/core/common/xml/pom.xml index ae86bb3bf9b..76184d6e127 100644 --- a/core/common/xml/pom.xml +++ b/core/common/xml/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-common - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-common-xml RDF4J: common XML diff --git a/core/http/client/pom.xml b/core/http/client/pom.xml index fa30ef4d812..8e26e6c8d3f 100644 --- a/core/http/client/pom.xml +++ b/core/http/client/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-http - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http-client RDF4J: HTTP client diff --git a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SharedHttpClientSessionManager.java b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SharedHttpClientSessionManager.java index 43412f081f9..eabcd1c51e2 100644 --- a/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SharedHttpClientSessionManager.java +++ b/core/http/client/src/main/java/org/eclipse/rdf4j/http/client/SharedHttpClientSessionManager.java @@ -45,23 +45,272 @@ * @author James Leigh */ public class SharedHttpClientSessionManager implements HttpClientSessionManager, HttpClientDependent { + + private static final AtomicLong threadCount = new AtomicLong(); + /** * Configurable system property {@code org.eclipse.rdf4j.client.executors.corePoolSize} for specifying the * background executor core thread pool size. */ public static final String CORE_POOL_SIZE_PROPERTY = "org.eclipse.rdf4j.client.executors.corePoolSize"; - private static final AtomicLong threadCount = new AtomicLong(); + /** + * Configurable system property {@code org.eclipse.rdf4j.client.http.maxConnPerRoute} for specifying the maximum + * number of connections per route (per host). Default is 25. + * + *

+ * This property determines the maximum number of concurrent connections to a single host (route). Adjusting this + * value can improve performance when communicating with a server that supports multiple concurrent connections. + *

+ */ + public static final String MAX_CONN_PER_ROUTE_PROPERTY = "org.eclipse.rdf4j.client.http.maxConnPerRoute"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.http.maxConnTotal} for specifying the maximum total + * number of connections. Default is 50. + * + *

+ * This property sets the maximum total number of concurrent connections that can be open at the same time. + * Increasing this value allows more simultaneous connections to different hosts, which can improve throughput in + * multi-threaded environments. + *

+ */ + public static final String MAX_CONN_TOTAL_PROPERTY = "org.eclipse.rdf4j.client.http.maxConnTotal"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.http.connectionTimeout} for specifying the HTTP + * connection timeout in milliseconds for general use. Default is 30 seconds. + * + *

+ * The connection timeout determines the maximum time the client will wait to establish a TCP connection to the + * server. A default of 30 seconds is set to allow for potential network delays without causing unnecessary + * timeouts. + *

+ */ + public static final String CONNECTION_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.http.connectionTimeout"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.http.connectionRequestTimeout} for specifying the + * HTTP connection request timeout in milliseconds for general use. Default is 1 hour. + * + *

+ * The connection request timeout defines how long the client will wait for a connection from the connection pool. + *

+ */ + public static final String CONNECTION_REQUEST_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.http.connectionRequestTimeout"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.http.socketTimeout} for specifying the HTTP socket + * timeout in milliseconds for general use. Default is 10 days. + * + *

+ * The socket timeout controls the maximum period of inactivity between data packets during data transfer. A longer + * timeout is appropriate for large data transfers, ensuring that operations are not interrupted prematurely. + *

+ */ + public static final String SOCKET_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.http.socketTimeout"; + + // System property constants for SPARQL SERVICE timeouts + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.connectionTimeout} for specifying the + * HTTP connection timeout in milliseconds when used in SPARQL SERVICE calls. Default is 5 seconds. + * + *

+ * A shorter connection timeout is set for SPARQL SERVICE calls to quickly detect unresponsive endpoints in + * federated queries, improving overall query performance by avoiding long waits for unreachable servers. + *

+ */ + public static final String SPARQL_CONNECTION_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.sparql.http.connectionTimeout"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.connectionRequestTimeout} for specifying + * the HTTP connection request timeout in milliseconds when used in SPARQL SERVICE calls. Default is 10 minutes. + * + *

+ * This timeout controls how long the client waits for a connection from the pool when making SPARQL SERVICE calls. + * A shorter timeout than general use ensures that queries fail fast if resources are constrained, maintaining + * responsiveness. + *

+ */ + public static final String SPARQL_CONNECTION_REQUEST_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.sparql.http.connectionRequestTimeout"; + + /** + * Configurable system property {@code org.eclipse.rdf4j.client.sparql.http.socketTimeout} for specifying the HTTP + * socket timeout in milliseconds when used in SPARQL SERVICE calls. Default is 1 hour. + * + *

+ * The socket timeout for SPARQL SERVICE calls is set to a shorter duration to detect unresponsive servers during + * data transfer, ensuring that the client does not wait indefinitely for data that may never arrive. + *

+ */ + public static final String SPARQL_SOCKET_TIMEOUT_PROPERTY = "org.eclipse.rdf4j.client.sparql.http.socketTimeout"; + + // Defaults + + /** + * Default core pool size for the executor service. Set to 5. + * + *

+ * This value determines the number of threads to keep in the pool, even if they are idle. Adjusting this value can + * help manage resource utilization in high-load scenarios. + *

+ */ + public static final int DEFAULT_CORE_POOL_SIZE = 5; + + /** + * Default maximum number of connections per route (per host). Set to 25. + * + *

+ * This value limits the number of concurrent connections to a single host. Increasing it can improve performance + * when communicating with a server that can handle multiple connections. + *

+ */ + public static final int DEFAULT_MAX_CONN_PER_ROUTE = 25; + + /** + * Default maximum total number of connections. Set to 50. + * + *

+ * This value limits the total number of concurrent connections that can be open at the same time. Increasing it + * allows for more simultaneous connections to different hosts. + *

+ */ + public static final int DEFAULT_MAX_CONN_TOTAL = 50; + + /** + * Default HTTP connection timeout in milliseconds for general use. Set to 30 seconds. + * + *

+ * The connection timeout determines the maximum time the client will wait to establish a TCP connection to the + * server. + *

+ */ + public static final int DEFAULT_CONNECTION_TIMEOUT = 30 * 1000; // 30 seconds + + /** + * Default HTTP connection request timeout in milliseconds for general use. Set to 1 hour. + * + *

+ * The connection request timeout defines how long the client will wait for a connection from the connection pool. + *

+ */ + public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 60 * 60 * 1000; // 1 hour + + /** + * Default HTTP socket timeout in milliseconds for general use. Set to 10 days. + * + *

+ * The socket timeout controls the maximum period of inactivity between data packets during data transfer. A longer + * timeout is appropriate for large data transfers. + *

+ */ + public static final int DEFAULT_SOCKET_TIMEOUT = 10 * 24 * 60 * 60 * 1000; // 10 days + + // Default timeout values for SPARQL SERVICE calls + + /** + * Default HTTP connection timeout in milliseconds for SPARQL SERVICE calls. Set to 5 seconds. + * + *

+ * A shorter connection timeout is set for SPARQL SERVICE calls to quickly detect unresponsive endpoints in + * federated queries. + *

+ */ + public static final int DEFAULT_SPARQL_CONNECTION_TIMEOUT = 5 * 1000; // 5 seconds + + /** + * Default HTTP connection request timeout in milliseconds for SPARQL SERVICE calls. Set to 10 minutes. + * + *

+ * This timeout controls how long the client waits for a connection from the pool when making SPARQL SERVICE calls. + *

+ */ + public static final int DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT = 10 * 60 * 1000; // 10 minutes + + /** + * Default HTTP socket timeout in milliseconds for SPARQL SERVICE calls. Set to 1 hour. + * + *

+ * The socket timeout for SPARQL SERVICE calls is set to a shorter duration to detect unresponsive servers during + * data transfer. + *

+ */ + public static final int DEFAULT_SPARQL_SOCKET_TIMEOUT = 60 * 60 * 1000; // 1 hour + + // Values as read from system properties or defaults + + /** + * Core pool size for the executor service, as read from system properties or defaults. + */ + public static final int CORE_POOL_SIZE = Integer + .parseInt(System.getProperty(CORE_POOL_SIZE_PROPERTY, String.valueOf(DEFAULT_CORE_POOL_SIZE))); + + /** + * Maximum number of connections per route (per host), as read from system properties or defaults. + */ + public static final int MAX_CONN_PER_ROUTE = Integer + .parseInt(System.getProperty(MAX_CONN_PER_ROUTE_PROPERTY, String.valueOf(DEFAULT_MAX_CONN_PER_ROUTE))); + + /** + * Maximum total number of connections, as read from system properties or defaults. + */ + public static final int MAX_CONN_TOTAL = Integer + .parseInt(System.getProperty(MAX_CONN_TOTAL_PROPERTY, String.valueOf(DEFAULT_MAX_CONN_TOTAL))); + + /** + * HTTP connection timeout in milliseconds for general use. + */ + public static final int CONNECTION_TIMEOUT = Integer.parseInt( + System.getProperty(CONNECTION_TIMEOUT_PROPERTY, String.valueOf(DEFAULT_CONNECTION_TIMEOUT))); + + /** + * HTTP connection request timeout in milliseconds for general use. + */ + public static final int CONNECTION_REQUEST_TIMEOUT = Integer.parseInt( + System.getProperty(CONNECTION_REQUEST_TIMEOUT_PROPERTY, + String.valueOf(DEFAULT_CONNECTION_REQUEST_TIMEOUT))); + + /** + * HTTP socket timeout in milliseconds for general use. + */ + public static final int SOCKET_TIMEOUT = Integer + .parseInt(System.getProperty(SOCKET_TIMEOUT_PROPERTY, String.valueOf(DEFAULT_SOCKET_TIMEOUT))); + + /** + * HTTP connection timeout in milliseconds for SPARQL SERVICE calls. + */ + public static final int SPARQL_CONNECTION_TIMEOUT = Integer.parseInt( + System.getProperty(SPARQL_CONNECTION_TIMEOUT_PROPERTY, String.valueOf(DEFAULT_SPARQL_CONNECTION_TIMEOUT))); + + /** + * HTTP connection request timeout in milliseconds for SPARQL SERVICE calls. + */ + public static final int SPARQL_CONNECTION_REQUEST_TIMEOUT = Integer.parseInt( + System.getProperty(SPARQL_CONNECTION_REQUEST_TIMEOUT_PROPERTY, + String.valueOf(DEFAULT_SPARQL_CONNECTION_REQUEST_TIMEOUT))); + + /** + * HTTP socket timeout in milliseconds for SPARQL SERVICE calls. + */ + public static final int SPARQL_SOCKET_TIMEOUT = Integer.parseInt( + System.getProperty(SPARQL_SOCKET_TIMEOUT_PROPERTY, String.valueOf(DEFAULT_SPARQL_SOCKET_TIMEOUT))); + + // Variables for the currently used timeouts + + private int currentConnectionTimeout = CONNECTION_TIMEOUT; + private int currentConnectionRequestTimeout = CONNECTION_REQUEST_TIMEOUT; + private int currentSocketTimeout = SOCKET_TIMEOUT; private final Logger logger = LoggerFactory.getLogger(SharedHttpClientSessionManager.class); /** - * independent life cycle + * Independent life cycle */ private volatile HttpClient httpClient; /** - * dependent life cycle + * Dependent life cycle */ private volatile CloseableHttpClient dependentClient; @@ -117,7 +366,7 @@ private static class ServiceUnavailableRetryHandler implements ServiceUnavailabl @Override public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { - // only retry on `408` + // only retry on HTTP 408 (Request Timeout) if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_CLIENT_TIMEOUT) { return false; } @@ -129,11 +378,10 @@ public boolean retryRequest(HttpResponse response, int executionCount, HttpConte return false; } - // worst case, the connection pool is filled to the max and all of them idled out on the server already - // we then need to clean up the pool and finally retry with a fresh connection. Hence, we need at most - // pooledConnections+1 retries. - // the pool size setting used here is taken from `HttpClientBuilder` when `useSystemProperties()` is used - int pooledConnections = Integer.parseInt(System.getProperty("http.maxConnections", "5")); + // Worst case, the connection pool is filled to the max and all of them idled out on the server already + // We then need to clean up the pool and retry with a fresh connection. Hence, we need at most + // pooledConnections + 1 retries. + int pooledConnections = MAX_CONN_PER_ROUTE; if (executionCount > (pooledConnections + 1)) { return false; } @@ -174,7 +422,7 @@ public SharedHttpClientSessionManager() { return thread; }); - Integer corePoolSize = Integer.getInteger(CORE_POOL_SIZE_PROPERTY, 1); + Integer corePoolSize = CORE_POOL_SIZE; ((ThreadPoolExecutor) threadPoolExecutor).setCorePoolSize(corePoolSize); this.executor = threadPoolExecutor; } @@ -267,6 +515,7 @@ public void close() { @Override public void shutDown() { try { + // Close open sessions openSessions.keySet().forEach(session -> { try { session.close(); @@ -280,11 +529,11 @@ public void shutDown() { HttpClientUtils.closeQuietly(toCloseDependentClient); } } finally { + // Shutdown the executor try { executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { - // Preserve the interrupt status so others can check it as necessary Thread.currentThread().interrupt(); } finally { if (!executor.isTerminated()) { @@ -314,17 +563,69 @@ protected final ExecutorService getExecutorService() { } private CloseableHttpClient createHttpClient() { + HttpClientBuilder nextHttpClientBuilder = httpClientBuilder; if (nextHttpClientBuilder != null) { return nextHttpClientBuilder.build(); } + RequestConfig requestConfig = getDefaultRequestConfig(); + return HttpClientBuilder.create() .evictExpiredConnections() + .evictIdleConnections(30, TimeUnit.MINUTES) .setRetryHandler(retryHandlerStale) .setServiceUnavailableRetryStrategy(serviceUnavailableRetryHandler) + .setMaxConnPerRoute(MAX_CONN_PER_ROUTE) + .setMaxConnTotal(MAX_CONN_TOTAL) .useSystemProperties() - .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()) + .setDefaultRequestConfig(requestConfig) .build(); } + + /** + * Returns the default {@link RequestConfig} using the currently set timeout values. + * + * @return a configured {@link RequestConfig} with the current timeouts. + */ + public RequestConfig getDefaultRequestConfig() { + return RequestConfig.custom() + .setConnectTimeout(currentConnectionTimeout) + .setConnectionRequestTimeout(currentConnectionRequestTimeout) + .setSocketTimeout(currentSocketTimeout) + .setCookieSpec(CookieSpecs.STANDARD) + .build(); + } + + /** + * Switches the current timeout settings to use the SPARQL-specific timeouts. This method should be called when + * making SPARQL SERVICE calls to apply shorter timeout values. + * + *

+ * The SPARQL-specific timeouts are shorter to ensure that unresponsive or slow SPARQL endpoints do not cause long + * delays in federated query processing. Quick detection of such issues improves the responsiveness and reliability + * of SPARQL queries. + *

+ */ + public void setDefaultSparqlServiceTimeouts() { + this.currentConnectionTimeout = SPARQL_CONNECTION_TIMEOUT; + this.currentConnectionRequestTimeout = SPARQL_CONNECTION_REQUEST_TIMEOUT; + this.currentSocketTimeout = SPARQL_SOCKET_TIMEOUT; + } + + /** + * Resets the current timeout settings to the general timeouts. This method should be called to revert any changes + * made by {@link #setDefaultSparqlServiceTimeouts()} and apply the general timeout values. + * + *

+ * The general timeouts are longer to accommodate operations that may take more time, such as large data transfers + * or extensive processing, without causing premature timeouts. + *

+ */ + public void setDefaultTimeouts() { + this.currentConnectionTimeout = CONNECTION_TIMEOUT; + this.currentConnectionRequestTimeout = CONNECTION_REQUEST_TIMEOUT; + this.currentSocketTimeout = SOCKET_TIMEOUT; + } + } diff --git a/core/http/pom.xml b/core/http/pom.xml index fb8565845b1..ee3e0261ad0 100644 --- a/core/http/pom.xml +++ b/core/http/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http pom diff --git a/core/http/protocol/pom.xml b/core/http/protocol/pom.xml index 74755a5a36e..a5d66a693e0 100644 --- a/core/http/protocol/pom.xml +++ b/core/http/protocol/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-http - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http-protocol RDF4J: HTTP protocol diff --git a/core/model-api/pom.xml b/core/model-api/pom.xml index 999e2bf07c6..cf07e38798c 100644 --- a/core/model-api/pom.xml +++ b/core/model-api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-model-api RDF4J: Model API diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Model.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Model.java index c409dd4eeed..3c83fdfc658 100644 --- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Model.java +++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Model.java @@ -45,7 +45,7 @@ public interface Model extends Set, Serializable, NamespaceAware { */ default Namespace setNamespace(String prefix, String name) { Optional result = getNamespace(prefix); - if (!result.isPresent() || !result.get().getName().equals(name)) { + if (result.isEmpty() || !result.get().getName().equals(name)) { result = Optional.of(new ModelNamespace(prefix, name)); setNamespace(result.get()); } diff --git a/core/model-vocabulary/pom.xml b/core/model-vocabulary/pom.xml index 830ed0d0c73..bd27791c1d8 100644 --- a/core/model-vocabulary/pom.xml +++ b/core/model-vocabulary/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-model-vocabulary RDF4J: RDF Vocabularies diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/AFN.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/AFN.java index db5a8f23ebb..c79391b6719 100644 --- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/AFN.java +++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/AFN.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.model.vocabulary; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; /** * http://jena.hpl.hp.com/ARQ/function#. @@ -27,6 +28,8 @@ private AFN() { public static final String PREFIX = "afn"; + public static final Namespace NS = Vocabularies.createNamespace(PREFIX, NAMESPACE); + /** * http://jena.hpl.hp.com/ARQ/function#localname The LocalName QueryModelNode as a SPARQL function. */ diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/APF.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/APF.java index bef3a96507d..af53de7dcd5 100644 --- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/APF.java +++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/APF.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.model.vocabulary; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; /** * http://jena.hpl.hp.com/ARQ/property#. @@ -27,6 +28,8 @@ private APF() { public static final String PREFIX = "apf"; + public static final Namespace NS = Vocabularies.createNamespace(PREFIX, NAMESPACE); + public static final IRI STR_SPLIT; public static final IRI CONCAT; diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCAT.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCAT.java index ab30b170392..bec91ff2bc3 100644 --- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCAT.java +++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/DCAT.java @@ -20,6 +20,7 @@ * @author Bart Hanssens * @see Data Catalog Vocabulary * @see Data Catalog Vocabulary version 2 + * @see Data Catalog Vocabulary version 3 */ public class DCAT { @@ -51,6 +52,9 @@ public class DCAT { /** dcat:Dataset */ public static final IRI DATASET; + /** dcat;DatasetSeries */ + public static final IRI DATASET_SERIES; + /** dcat:Distribution */ public static final IRI DISTRIBUTION; @@ -97,12 +101,18 @@ public class DCAT { /** dcat:endpointURL */ public static final IRI ENDPOINT_URL; + /** dcat;first */ + public static final IRI FIRST; + /** dcat:hadRole */ public static final IRI HAD_ROLE; /** dcat:catalog */ public static final IRI HAS_CATALOG; + /** dcat:hasCurrentVersion */ + public static final IRI HAS_CURRENT_VERSION; + /** dcat:dataset */ public static final IRI HAS_DATASET; @@ -115,18 +125,48 @@ public class DCAT { /** dcat:service */ public static final IRI HAS_SERVICE; + /** dcat;inCatalog, inverse property, see section 7 of DCAT v3 */ + public static final IRI IN_CATALOG; + + /** dcat:inSeries */ + public static final IRI IN_SERIES; + + /** dcat:isDistributionOf, inverse property, see section 7 of DCAT v3 */ + public static final IRI IS_DISTRIBUTION_OF; + + /** dcat:isVersionOf, inverse property, see section 7 of DCAT v3 */ + public static final IRI IS_VERSION_OF; + /** dcat:keyword */ public static final IRI KEYWORD; /** dcat:landingPage */ public static final IRI LANDING_PAGE; + /** dcat:last */ + public static final IRI LAST; + /** dcat:mediaType */ public static final IRI MEDIA_TYPE; + /** dcat:next, inverse property, see section 7 of DCAT v3 */ + public static final IRI NEXT; + + /** dcat:nextVersion, inverse property, see section 7 of DCAT v3 */ + public static final IRI NEXT_VERSION; + /** dcat:packageFormat */ public static final IRI PACKAGE_FORMAT; + /** dcat:prev */ + public static final IRI PREV; + + /** dcat:previousVersion */ + public static final IRI PREVIOUS_VERSION; + + /** dcat:seriesMember, inverse property, see section 7 of DCAT v3 */ + public static final IRI SERIES_MEMBER; + /** dcat:qualifiedRelation */ public static final IRI QUALIFIED_RELATION; @@ -148,12 +188,16 @@ public class DCAT { /** dcat:themeTaxonomy */ public static final IRI THEME_TAXONOMY; + /** dcat:version */ + public static final IRI VERSION; + static { CATALOG = Vocabularies.createIRI(NAMESPACE, "Catalog"); CATALOG_RECORD = Vocabularies.createIRI(NAMESPACE, "CatalogRecord"); DATA_SERVICE = Vocabularies.createIRI(NAMESPACE, "DataService"); DATASET = Vocabularies.createIRI(NAMESPACE, "Dataset"); + DATASET_SERIES = Vocabularies.createIRI(NAMESPACE, "DatasetSeries"); DISTRIBUTION = Vocabularies.createIRI(NAMESPACE, "Distribution"); RELATIONSHIP = Vocabularies.createIRI(NAMESPACE, "Relationship"); RESOURCE = Vocabularies.createIRI(NAMESPACE, "Resource"); @@ -170,22 +214,35 @@ public class DCAT { END_DATE = Vocabularies.createIRI(NAMESPACE, "endDate"); ENDPOINT_DESCRIPTION = Vocabularies.createIRI(NAMESPACE, "endpointDescription"); ENDPOINT_URL = Vocabularies.createIRI(NAMESPACE, "endpointURL"); + FIRST = Vocabularies.createIRI(NAMESPACE, "first"); HAD_ROLE = Vocabularies.createIRI(NAMESPACE, "hadRole"); HAS_CATALOG = Vocabularies.createIRI(NAMESPACE, "catalog"); HAS_DATASET = Vocabularies.createIRI(NAMESPACE, "dataset"); + HAS_CURRENT_VERSION = Vocabularies.createIRI(NAMESPACE, "hasCurrentVersion"); HAS_DISTRIBUTION = Vocabularies.createIRI(NAMESPACE, "distribution"); HAS_RECORD = Vocabularies.createIRI(NAMESPACE, "record"); HAS_SERVICE = Vocabularies.createIRI(NAMESPACE, "service"); + IN_CATALOG = Vocabularies.createIRI(NAMESPACE, "inCatalog"); + IN_SERIES = Vocabularies.createIRI(NAMESPACE, "inSeries"); + IS_DISTRIBUTION_OF = Vocabularies.createIRI(NAMESPACE, "isDistributionOf"); + IS_VERSION_OF = Vocabularies.createIRI(NAMESPACE, "isVersionOf"); KEYWORD = Vocabularies.createIRI(NAMESPACE, "keyword"); LANDING_PAGE = Vocabularies.createIRI(NAMESPACE, "landingPage"); + LAST = Vocabularies.createIRI(NAMESPACE, "last"); MEDIA_TYPE = Vocabularies.createIRI(NAMESPACE, "mediaType"); + NEXT = Vocabularies.createIRI(NAMESPACE, "next"); + NEXT_VERSION = Vocabularies.createIRI(NAMESPACE, "nextVersion"); PACKAGE_FORMAT = Vocabularies.createIRI(NAMESPACE, "packageFormat"); + PREV = Vocabularies.createIRI(NAMESPACE, "prev"); + PREVIOUS_VERSION = Vocabularies.createIRI(NAMESPACE, "previousVersion"); QUALIFIED_RELATION = Vocabularies.createIRI(NAMESPACE, "qualifiedRelation"); + SERIES_MEMBER = Vocabularies.createIRI(NAMESPACE, "seriesMember"); SERVES_DATASET = Vocabularies.createIRI(NAMESPACE, "servesDataset"); SPATIAL_RESOLUTION_IN_METERS = Vocabularies.createIRI(NAMESPACE, "spatialResolutionInMeters"); START_DATE = Vocabularies.createIRI(NAMESPACE, "startDate"); TEMPORAL_RESOLUTION = Vocabularies.createIRI(NAMESPACE, "temporalResolution"); THEME = Vocabularies.createIRI(NAMESPACE, "theme"); THEME_TAXONOMY = Vocabularies.createIRI(NAMESPACE, "themeTaxonomy"); + VERSION = Vocabularies.createIRI(NAMESPACE, "version"); } } diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java index 8b5d96c8a63..3565ae8f5d1 100644 --- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java +++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/EARL.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.model.vocabulary; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; /** * Constants for EARL primitives and for the EARL namespace. @@ -27,6 +28,8 @@ public class EARL { */ public static final String PREFIX = "earl"; + public static final Namespace NS = Vocabularies.createNamespace(PREFIX, NAMESPACE); + public final static IRI ASSERTOR; public final static IRI ASSERTION; diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java index 954c51ea0b1..56ed00f3e83 100644 --- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java +++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/GEOF.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.model.vocabulary; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; /** * @see org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-model RDF4J: Model diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Configurations.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Configurations.java index b74e2f84ec4..7c9bb003ea2 100644 --- a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Configurations.java +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Configurations.java @@ -240,7 +240,7 @@ public static Optional getSubjectByType(Model model, IRI type, IRI leg private static void logDiscrepancyWarning(Optional preferred, Optional fallback) { - if (!fallback.isEmpty() && !preferred.equals(fallback)) { + if (fallback.isPresent() && !preferred.equals(fallback)) { var msg = "Discrepancy between use of the old and new config vocabulary."; // depending on whether preferred is set, we log on warn or debug if (preferred.isEmpty()) { diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphComparisons.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphComparisons.java index 0c5911ee00f..1f3ceb59c80 100644 --- a/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphComparisons.java +++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/GraphComparisons.java @@ -169,7 +169,7 @@ private static boolean isomorphicSingleContext(Model model1, Model model2) { // Because we have previously already checked that the models are the same size, we don't have to check both // ways to establish model equality. - return !missingInModel2.isPresent(); + return missingInModel2.isEmpty(); } private static boolean mappingsIncompatible(Map mapping1, Map mapping2) { diff --git a/core/pom.xml b/core/pom.xml index c6cad1c1dbc..ed94faedcde 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-core pom diff --git a/core/query/pom.xml b/core/query/pom.xml index fd2e3aaf2b9..6600bd51a4e 100644 --- a/core/query/pom.xml +++ b/core/query/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-query RDF4J: Query diff --git a/core/queryalgebra/evaluation/pom.xml b/core/queryalgebra/evaluation/pom.xml index b82eaf35463..a29c5f1ab29 100644 --- a/core/queryalgebra/evaluation/pom.xml +++ b/core/queryalgebra/evaluation/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryalgebra - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryalgebra-evaluation RDF4J: Query algebra - evaluation diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java index df4b84dd32a..8e5c5191cdf 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java @@ -45,7 +45,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx Literal rightLit = (Literal) rightVal; if (leftLit.getLanguage().isPresent()) { - if (!rightLit.getLanguage().isPresent() || rightLit.getLanguage().equals(leftLit.getLanguage())) { + if (rightLit.getLanguage().isEmpty() || rightLit.getLanguage().equals(leftLit.getLanguage())) { String leftLexVal = leftLit.getLabel(); String rightLexVal = rightLit.getLabel(); diff --git a/core/queryalgebra/geosparql/pom.xml b/core/queryalgebra/geosparql/pom.xml index 4624020fb40..10fcbc837ce 100644 --- a/core/queryalgebra/geosparql/pom.xml +++ b/core/queryalgebra/geosparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryalgebra - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryalgebra-geosparql RDF4J: Query algebra - GeoSPARQL diff --git a/core/queryalgebra/model/pom.xml b/core/queryalgebra/model/pom.xml index 4c7df28ee81..c561441a066 100644 --- a/core/queryalgebra/model/pom.xml +++ b/core/queryalgebra/model/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryalgebra - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryalgebra-model RDF4J: Query algebra - model diff --git a/core/queryalgebra/pom.xml b/core/queryalgebra/pom.xml index b89e1012d31..fb04d8339cd 100644 --- a/core/queryalgebra/pom.xml +++ b/core/queryalgebra/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryalgebra pom diff --git a/core/queryparser/api/pom.xml b/core/queryparser/api/pom.xml index 3c8aae2e1b3..6450c375f42 100644 --- a/core/queryparser/api/pom.xml +++ b/core/queryparser/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryparser - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryparser-api RDF4J: Query parser - API diff --git a/core/queryparser/pom.xml b/core/queryparser/pom.xml index 2dad1fcf022..0dfcb8573d3 100644 --- a/core/queryparser/pom.xml +++ b/core/queryparser/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryparser pom diff --git a/core/queryparser/sparql/pom.xml b/core/queryparser/sparql/pom.xml index 58013a511d0..d21ecf2b1b2 100644 --- a/core/queryparser/sparql/pom.xml +++ b/core/queryparser/sparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryparser - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryparser-sparql RDF4J: Query parser - SPARQL diff --git a/core/queryrender/pom.xml b/core/queryrender/pom.xml index 5c837892ad1..8db12169a80 100644 --- a/core/queryrender/pom.xml +++ b/core/queryrender/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryrender RDF4J: Query Rendering diff --git a/core/queryresultio/api/pom.xml b/core/queryresultio/api/pom.xml index c0682af50f0..273fe3b9801 100644 --- a/core/queryresultio/api/pom.xml +++ b/core/queryresultio/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryresultio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-api RDF4J: Query result IO - API diff --git a/core/queryresultio/binary/pom.xml b/core/queryresultio/binary/pom.xml index 9c8f044621c..34df6c0b64f 100644 --- a/core/queryresultio/binary/pom.xml +++ b/core/queryresultio/binary/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryresultio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-binary RDF4J: Query result IO - binary diff --git a/core/queryresultio/pom.xml b/core/queryresultio/pom.xml index 5532a815d4c..c1ba95a8c53 100644 --- a/core/queryresultio/pom.xml +++ b/core/queryresultio/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio pom diff --git a/core/queryresultio/sparqljson/pom.xml b/core/queryresultio/sparqljson/pom.xml index da368bfb36e..c5f589b6457 100644 --- a/core/queryresultio/sparqljson/pom.xml +++ b/core/queryresultio/sparqljson/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryresultio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-sparqljson RDF4J: Query result IO - SPARQL/JSON diff --git a/core/queryresultio/sparqlxml/pom.xml b/core/queryresultio/sparqlxml/pom.xml index 3e2292024eb..8d7bee2745b 100644 --- a/core/queryresultio/sparqlxml/pom.xml +++ b/core/queryresultio/sparqlxml/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryresultio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-sparqlxml RDF4J: Query result IO - SPARQL/XML diff --git a/core/queryresultio/text/pom.xml b/core/queryresultio/text/pom.xml index 3e95d66738e..e5f67e0b32e 100644 --- a/core/queryresultio/text/pom.xml +++ b/core/queryresultio/text/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-queryresultio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-text RDF4J: Query result IO - plain text booleans diff --git a/core/repository/api/pom.xml b/core/repository/api/pom.xml index 5e16576f662..48fdeecfad7 100644 --- a/core/repository/api/pom.xml +++ b/core/repository/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-api RDF4J: Repository - API diff --git a/core/repository/contextaware/pom.xml b/core/repository/contextaware/pom.xml index 3ae8aea353f..39bcbf0668c 100644 --- a/core/repository/contextaware/pom.xml +++ b/core/repository/contextaware/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-contextaware RDF4J: Repository - context aware (wrapper) diff --git a/core/repository/dataset/pom.xml b/core/repository/dataset/pom.xml index c601265c72b..c843dccda42 100644 --- a/core/repository/dataset/pom.xml +++ b/core/repository/dataset/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-dataset RDF4J: DatasetRepository (wrapper) diff --git a/core/repository/event/pom.xml b/core/repository/event/pom.xml index 05dbbc70276..3a3109cf967 100644 --- a/core/repository/event/pom.xml +++ b/core/repository/event/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-event RDF4J: Repository - event (wrapper) diff --git a/core/repository/http/pom.xml b/core/repository/http/pom.xml index 2ed36d9acfc..4fc07dc06e9 100644 --- a/core/repository/http/pom.xml +++ b/core/repository/http/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-http RDF4J: HTTPRepository diff --git a/core/repository/manager/pom.xml b/core/repository/manager/pom.xml index 56ba4f7066e..bad53d7101e 100644 --- a/core/repository/manager/pom.xml +++ b/core/repository/manager/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-manager RDF4J: Repository manager diff --git a/core/repository/pom.xml b/core/repository/pom.xml index 494eb65b759..873757a9580 100644 --- a/core/repository/pom.xml +++ b/core/repository/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository pom diff --git a/core/repository/sail/pom.xml b/core/repository/sail/pom.xml index fa88c985bb8..fb8fc483b2b 100644 --- a/core/repository/sail/pom.xml +++ b/core/repository/sail/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-sail RDF4J: SailRepository diff --git a/core/repository/sparql/pom.xml b/core/repository/sparql/pom.xml index 6e259f6c8b9..66d5ee263ce 100644 --- a/core/repository/sparql/pom.xml +++ b/core/repository/sparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-repository - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-sparql RDF4J: SPARQL Repository diff --git a/core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/federation/SPARQLServiceResolver.java b/core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/federation/SPARQLServiceResolver.java index 6165d2bd437..7cc7a29bd23 100644 --- a/core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/federation/SPARQLServiceResolver.java +++ b/core/repository/sparql/src/main/java/org/eclipse/rdf4j/repository/sparql/federation/SPARQLServiceResolver.java @@ -76,7 +76,19 @@ public void setHttpClientSessionManager(HttpClientSessionManager client) { @Override public HttpClient getHttpClient() { - return getHttpClientSessionManager().getHttpClient(); + HttpClientSessionManager httpClientSessionManager = getHttpClientSessionManager(); + + try { + if (httpClientSessionManager instanceof SharedHttpClientSessionManager) { + ((SharedHttpClientSessionManager) httpClientSessionManager).setDefaultSparqlServiceTimeouts(); + } + return getHttpClientSessionManager().getHttpClient(); + } finally { + if (httpClientSessionManager instanceof SharedHttpClientSessionManager) { + ((SharedHttpClientSessionManager) httpClientSessionManager).setDefaultTimeouts(); + } + } + } @Override @@ -86,6 +98,7 @@ public void setHttpClient(HttpClient httpClient) { getHttpClientSessionManager(); toSetDependentClient = dependentClient; } + // The strange lifecycle results in the possibility that the // dependentClient will be null due to a call to setSesameClient, so add // a null guard here for that possibility diff --git a/core/rio/api/pom.xml b/core/rio/api/pom.xml index 21ffd854962..3733b074423 100644 --- a/core/rio/api/pom.xml +++ b/core/rio/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-api RDF4J: Rio - API diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioConfig.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioConfig.java index da2ce985441..cfeb053ede9 100644 --- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioConfig.java +++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/RioConfig.java @@ -11,6 +11,10 @@ package org.eclipse.rdf4j.rio; import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -152,4 +156,8 @@ public RioConfig useDefaults() { systemPropertyCache.clear(); return this; } + + public Map, Object> getSettings() { + return Collections.unmodifiableMap(new HashMap<>(settings)); + } } diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDSettings.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDSettings.java index 70b37632553..637451953e2 100644 --- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDSettings.java +++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/JSONLDSettings.java @@ -35,7 +35,6 @@ public class JSONLDSettings { * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.compact_arrays}. * * @see JSONLD Data Structures - * */ public static final BooleanRioSetting COMPACT_ARRAYS = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.compact_arrays", "Compact arrays", Boolean.TRUE); @@ -43,7 +42,6 @@ public class JSONLDSettings { /** * If specified, it is used to retrieve remote documents and contexts; otherwise the processor's built-in loader is * used. - * */ public static final RioSetting DOCUMENT_LOADER = new ClassRioSetting<>( "org.eclipse.rdf4j.rio.jsonld.document_loader", "Document loader", null); @@ -66,7 +64,6 @@ public class JSONLDSettings { /** * The JSON-LD processor will throw an exception if a warning is encountered during processing. - * */ public static final BooleanRioSetting EXCEPTION_ON_WARNING = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.exception_on_warning", @@ -83,7 +80,6 @@ public class JSONLDSettings { * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.optimize}. * * @see JSONLD Data Structures - * */ public static final BooleanRioSetting OPTIMIZE = new BooleanRioSetting("org.eclipse.rdf4j.rio.jsonld.optimize", "Optimize output", Boolean.FALSE); @@ -99,7 +95,6 @@ public class JSONLDSettings { * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.produce_generalized_rdf}. * * @see JSONLD Data Structures - * */ public static final BooleanRioSetting PRODUCE_GENERALIZED_RDF = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.produce_generalized_rdf", "Produce generalized RDF", Boolean.FALSE); @@ -114,7 +109,6 @@ public class JSONLDSettings { * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.use_native_types}. * * @see JSONLD Data Structures - * */ public static final BooleanRioSetting USE_NATIVE_TYPES = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.use_native_types", "Use Native JSON Types", Boolean.FALSE); @@ -128,7 +122,6 @@ public class JSONLDSettings { * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.use_rdf_type}. * * @see JSONLD Data Structures - * */ public static final BooleanRioSetting USE_RDF_TYPE = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.use_rdf_type", "Use RDF Type", Boolean.FALSE); @@ -139,7 +132,6 @@ public class JSONLDSettings { * Defaults to {@link JSONLDMode#EXPAND} to provide maximum RDF compatibility. * * @see JSONLD Features - * */ public static final RioSetting JSONLD_MODE = new RioSettingImpl<>( "org.eclipse.rdf4j.rio.jsonld_mode", "JSONLD Mode", JSONLDMode.EXPAND); @@ -150,7 +142,6 @@ public class JSONLDSettings { * Default to false *

* Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.hierarchical_view}. - * */ public static final BooleanRioSetting HIERARCHICAL_VIEW = new BooleanRioSetting( "org.eclipse.rdf4j.rio.jsonld.hierarchical_view", "Hierarchical representation of the JSON", Boolean.FALSE); @@ -161,38 +152,88 @@ public class JSONLDSettings { * array of the desired values. *

* Default: - * {@code Set.of("http://www.w3.org/ns/anno.jsonld", "http://www.w3.org/ns/activitystreams.jsonld", "http://www.w3.org/ns/ldp.jsonld", "http://www.w3.org/ns/oa.jsonld", "http://www.w3.org/ns/hydra/context.jsonld", "http://schema.org/", "https://w3id.org/security/v1", "https://w3c.github.io/json-ld-rc/context.jsonld", "https://www.w3.org/2018/credentials/v1", "https://health-lifesci.schema.org/", "https://auto.schema.org/", "https://bib.schema.org/", "http://xmlns.com/foaf/spec/index.jsonld", "https://pending.schema.org/", "https://schema.org/", "https://schema.org/docs/jsonldcontext.jsonld", "https://schema.org/version/latest/schemaorg-current-https.jsonld", "https://schema.org/version/latest/schemaorg-all-http.jsonld", "https://schema.org/version/latest/schemaorg-all-https.jsonld", "https://schema.org/version/latest/schemaorg-current-http.jsonld", "https://schema.org/version/latest/schemaorg-all.jsonld", "https://schema.org/version/latest/schemaorg-current.jsonld", "https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "https://geojson.org/geojson-ld/geojson-context.jsonld", "https://www.w3.org/2019/wot/td/v1"); - * + * {@code Set.of("http://www.w3.org/ns/anno.jsonld", "https://www.w3.org/ns/anno.jsonld", "http://www.w3.org/ns/anno", "https://www.w3.org/ns/anno", "http://www.w3.org/ns/activitystreams.jsonld", "https://www.w3.org/ns/activitystreams.jsonld", "http://www.w3.org/ns/activitystreams", "https://www.w3.org/ns/activitystreams", "http://www.w3.org/ns/ldp.jsonld", "https://www.w3.org/ns/ldp.jsonld", "http://www.w3.org/ns/ldp", "https://www.w3.org/ns/ldp", "http://www.w3.org/ns/oa.jsonld", "https://www.w3.org/ns/oa.jsonld", "http://www.w3.org/ns/oa", "https://www.w3.org/ns/oa", "http://www.w3.org/ns/hydra/context.jsonld", "https://www.w3.org/ns/hydra/context.jsonld", "http://www.w3.org/ns/hydra/context", "https://www.w3.org/ns/hydra/context", "http://www.w3.org/2018/credentials/v1.jsonld", "https://www.w3.org/2018/credentials/v1.jsonld", "http://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/v1", "http://www.w3.org/2019/wot/td/v1.jsonld", "https://www.w3.org/2019/wot/td/v1.jsonld", "http://www.w3.org/2019/wot/td/v1", "https://www.w3.org/2019/wot/td/v1", "http://w3c.github.io/json-ld-rc/context.jsonld", "https://w3c.github.io/json-ld-rc/context.jsonld", "http://schema.org/", "https://schema.org/", "http://health-lifesci.schema.org/", "https://health-lifesci.schema.org/", "http://auto.schema.org/", "https://auto.schema.org/", "http://bib.schema.org/", "https://bib.schema.org/", "http://pending.schema.org/", "https://pending.schema.org/", "http://schema.org", "https://schema.org", "http://health-lifesci.schema.org", "https://health-lifesci.schema.org", "http://auto.schema.org", "https://auto.schema.org", "http://bib.schema.org", "https://bib.schema.org", "http://pending.schema.org", "https://pending.schema.org", "http://schema.org/docs/jsonldcontext.jsonld", "https://schema.org/docs/jsonldcontext.jsonld", "http://schema.org/version/latest/schemaorg-current-https.jsonld", "https://schema.org/version/latest/schemaorg-current-https.jsonld", "http://schema.org/version/latest/schemaorg-all-http.jsonld", "https://schema.org/version/latest/schemaorg-all-http.jsonld", "http://schema.org/version/latest/schemaorg-all-https.jsonld", "https://schema.org/version/latest/schemaorg-all-https.jsonld", "http://schema.org/version/latest/schemaorg-current-http.jsonld", "https://schema.org/version/latest/schemaorg-current-http.jsonld", "http://schema.org/version/latest/schemaorg-all.jsonld", "https://schema.org/version/latest/schemaorg-all.jsonld", "http://schema.org/version/latest/schemaorg-current.jsonld", "https://schema.org/version/latest/schemaorg-current.jsonld", "http://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "http://geojson.org/geojson-ld/geojson-context.jsonld", "https://geojson.org/geojson-ld/geojson-context.jsonld", "http://w3id.org/security/v1", "https://w3id.org/security/v1", "http://xmlns.com/foaf/spec/index.jsonld", "https://xmlns.com/foaf/spec/index.jsonld", "http://xmlns.com/foaf/spec/", "https://xmlns.com/foaf/spec/", "http://xmlns.com/foaf/spec", "https://xmlns.com/foaf/spec")} */ public static final SetRioSetting WHITELIST = new SetRioSetting<>( "org.eclipse.rdf4j.rio.jsonld_whitelist", "Whitelist of remote/local resources that the JSON-LD parser can retrieve. Set of URIs as strings.", Set.of( "http://www.w3.org/ns/anno.jsonld", + "https://www.w3.org/ns/anno.jsonld", + "http://www.w3.org/ns/anno", + "https://www.w3.org/ns/anno", "http://www.w3.org/ns/activitystreams.jsonld", + "https://www.w3.org/ns/activitystreams.jsonld", + "http://www.w3.org/ns/activitystreams", + "https://www.w3.org/ns/activitystreams", "http://www.w3.org/ns/ldp.jsonld", + "https://www.w3.org/ns/ldp.jsonld", + "http://www.w3.org/ns/ldp", + "https://www.w3.org/ns/ldp", "http://www.w3.org/ns/oa.jsonld", + "https://www.w3.org/ns/oa.jsonld", + "http://www.w3.org/ns/oa", + "https://www.w3.org/ns/oa", "http://www.w3.org/ns/hydra/context.jsonld", - "http://schema.org/", - "https://w3id.org/security/v1", - "https://w3c.github.io/json-ld-rc/context.jsonld", + "https://www.w3.org/ns/hydra/context.jsonld", + "http://www.w3.org/ns/hydra/context", + "https://www.w3.org/ns/hydra/context", + "http://www.w3.org/2018/credentials/v1.jsonld", + "https://www.w3.org/2018/credentials/v1.jsonld", + "http://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/v1", + "http://www.w3.org/2019/wot/td/v1.jsonld", + "https://www.w3.org/2019/wot/td/v1.jsonld", + "http://www.w3.org/2019/wot/td/v1", + "https://www.w3.org/2019/wot/td/v1", + "http://w3c.github.io/json-ld-rc/context.jsonld", + "https://w3c.github.io/json-ld-rc/context.jsonld", + "http://schema.org/", + "https://schema.org/", + "http://health-lifesci.schema.org/", "https://health-lifesci.schema.org/", + "http://auto.schema.org/", "https://auto.schema.org/", + "http://bib.schema.org/", "https://bib.schema.org/", - "http://xmlns.com/foaf/spec/index.jsonld", + "http://pending.schema.org/", "https://pending.schema.org/", - "https://schema.org/", + "http://schema.org", + "https://schema.org", + "http://health-lifesci.schema.org", + "https://health-lifesci.schema.org", + "http://auto.schema.org", + "https://auto.schema.org", + "http://bib.schema.org", + "https://bib.schema.org", + "http://pending.schema.org", + "https://pending.schema.org", + "http://schema.org/docs/jsonldcontext.jsonld", "https://schema.org/docs/jsonldcontext.jsonld", + "http://schema.org/version/latest/schemaorg-current-https.jsonld", "https://schema.org/version/latest/schemaorg-current-https.jsonld", + "http://schema.org/version/latest/schemaorg-all-http.jsonld", "https://schema.org/version/latest/schemaorg-all-http.jsonld", + "http://schema.org/version/latest/schemaorg-all-https.jsonld", "https://schema.org/version/latest/schemaorg-all-https.jsonld", + "http://schema.org/version/latest/schemaorg-current-http.jsonld", "https://schema.org/version/latest/schemaorg-current-http.jsonld", + "http://schema.org/version/latest/schemaorg-all.jsonld", "https://schema.org/version/latest/schemaorg-all.jsonld", + "http://schema.org/version/latest/schemaorg-current.jsonld", "https://schema.org/version/latest/schemaorg-current.jsonld", + "http://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", + "http://geojson.org/geojson-ld/geojson-context.jsonld", "https://geojson.org/geojson-ld/geojson-context.jsonld", - "https://www.w3.org/2019/wot/td/v1" + "http://w3id.org/security/v1", + "https://w3id.org/security/v1", + "http://xmlns.com/foaf/spec/index.jsonld", + "https://xmlns.com/foaf/spec/index.jsonld", + "http://xmlns.com/foaf/spec/", + "https://xmlns.com/foaf/spec/", + "http://xmlns.com/foaf/spec", + "https://xmlns.com/foaf/spec" )); /** diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java index 3d9d0f5414e..fbb27d608ab 100644 --- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java +++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java @@ -190,7 +190,7 @@ public static Literal createLiteral(String label, String lang, IRI datatype, Par try { // Removes datatype for langString datatype with no language tag when VERIFY_DATATYPE_VALUES is False. if ((workingDatatype == null || RDF.LANGSTRING.equals(workingDatatype)) - && (!workingLang.isPresent() || workingLang.get().isEmpty()) + && (workingLang.isEmpty() || workingLang.get().isEmpty()) && !parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)) { workingLang = Optional.ofNullable(null); workingDatatype = null; diff --git a/core/rio/binary/pom.xml b/core/rio/binary/pom.xml index e59d2265ff9..4ff5469eddf 100644 --- a/core/rio/binary/pom.xml +++ b/core/rio/binary/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-binary RDF4J: Rio - Binary diff --git a/core/rio/datatypes/pom.xml b/core/rio/datatypes/pom.xml index 4b8d0d984f7..b9d9dcadcfb 100644 --- a/core/rio/datatypes/pom.xml +++ b/core/rio/datatypes/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-datatypes RDF4J: Rio - Datatypes diff --git a/core/rio/hdt/pom.xml b/core/rio/hdt/pom.xml index c8311ec8f3d..f3647663a65 100644 --- a/core/rio/hdt/pom.xml +++ b/core/rio/hdt/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-hdt jar diff --git a/core/rio/jsonld-legacy/pom.xml b/core/rio/jsonld-legacy/pom.xml index f9574448da9..7509ef4b834 100644 --- a/core/rio/jsonld-legacy/pom.xml +++ b/core/rio/jsonld-legacy/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-jsonld-legacy RDF4J: Rio - JSON-LD 1.0 (legacy) diff --git a/core/rio/jsonld-legacy/src/main/java/org/eclipse/rdf4j/rio/jsonld/legacy/JSONLDInternalRDFParser.java b/core/rio/jsonld-legacy/src/main/java/org/eclipse/rdf4j/rio/jsonld/legacy/JSONLDInternalRDFParser.java index f61f310ef3a..2bb9232b2e2 100644 --- a/core/rio/jsonld-legacy/src/main/java/org/eclipse/rdf4j/rio/jsonld/legacy/JSONLDInternalRDFParser.java +++ b/core/rio/jsonld-legacy/src/main/java/org/eclipse/rdf4j/rio/jsonld/legacy/JSONLDInternalRDFParser.java @@ -64,7 +64,7 @@ public void handleStatement(RDFDataset result, Statement nextStatement) { // In RDF-1.1, RDF-1.0 Plain Literals are now Typed Literals with // type xsd:String - if (!literal.getLanguage().isPresent() && datatype == null) { + if (literal.getLanguage().isEmpty() && datatype == null) { datatype = XSD.STRING.stringValue(); } diff --git a/core/rio/jsonld/pom.xml b/core/rio/jsonld/pom.xml index ba1528865a2..c817e4db0af 100644 --- a/core/rio/jsonld/pom.xml +++ b/core/rio/jsonld/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-jsonld RDF4J: Rio - JSON-LD diff --git a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/CachingDocumentLoader.java b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/CachingDocumentLoader.java index c4363a1f4db..aea446626c4 100644 --- a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/CachingDocumentLoader.java +++ b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/CachingDocumentLoader.java @@ -37,7 +37,7 @@ public class CachingDocumentLoader implements DocumentLoader { private static final LoadingCache cache = CacheBuilder.newBuilder() .maximumSize(1000) // Maximum 1000 documents in cache .expireAfterWrite(1, TimeUnit.HOURS) // Expire after 1 hour - .concurrencyLevel(8) // Optimize for 8 concurrent threads + .concurrencyLevel(Runtime.getRuntime().availableProcessors()) .build(new CacheLoader<>() { @Override public Document load(URI url) throws Exception { diff --git a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDMode.java b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDMode.java new file mode 100644 index 00000000000..819ecf284d1 --- /dev/null +++ b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDMode.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * + * 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.rio.jsonld; + +/** + * Specifies constants to identify various modes that are relevant to JSONLD documents. + * + * @author Peter Ansell + * @see JSONLD Features + * + */ +public enum JSONLDMode { + + EXPAND("Expansion", "http://json-ld.org/spec/latest/json-ld-api/index.html#expansion"), + + COMPACT("Compaction", "http://json-ld.org/spec/latest/json-ld-api/index.html#compaction"), + + FLATTEN("Flattening", "http://json-ld.org/spec/latest/json-ld-api/index.html#flattening"), + + FRAME("Framing", "https://www.w3.org/TR/json-ld11-framing/"), + + ; + + private final String label; + + private final String reference; + + JSONLDMode(String label, String reference) { + this.label = label; + this.reference = reference; + } + + /** + * @return Returns the label. + */ + public String getLabel() { + return label; + } + + /** + * @return Returns the reference URL for the given mode. + */ + public String getReference() { + return reference; + } +} diff --git a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParser.java b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParser.java index 69c09c92906..646b47958dc 100644 --- a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParser.java +++ b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParser.java @@ -10,16 +10,13 @@ *******************************************************************************/ package org.eclipse.rdf4j.rio.jsonld; -import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.DOCUMENT_LOADER_CACHE; -import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.SECURE_MODE; -import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.WHITELIST; - import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; @@ -35,10 +32,11 @@ import org.eclipse.rdf4j.rio.RDFHandlerException; import org.eclipse.rdf4j.rio.RDFParseException; import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RioConfig; import org.eclipse.rdf4j.rio.RioSetting; import org.eclipse.rdf4j.rio.helpers.AbstractRDFParser; import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; -import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; +import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,6 +89,13 @@ public Collection> getSupportedSettings() { result.add(JSONLDSettings.EXPAND_CONTEXT); result.add(JSONLDSettings.EXCEPTION_ON_WARNING); + result.add(JSONLDSettings.SECURE_MODE); + result.add(JSONLDSettings.WHITELIST); + result.add(JSONLDSettings.DOCUMENT_LOADER); + result.add(JSONLDSettings.DOCUMENT_LOADER_CACHE); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.SECURE_MODE); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.WHITELIST); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.DOCUMENT_LOADER_CACHE); return result; } @@ -133,9 +138,9 @@ private void parse(InputStream in, Reader reader, String baseURI) BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES); } - boolean secureMode = getParserConfig().get(SECURE_MODE); - Set whitelist = getParserConfig().get(WHITELIST); - boolean documentLoaderCache = getParserConfig().get(DOCUMENT_LOADER_CACHE); + boolean secureMode = getParserConfig().get(JSONLDSettings.SECURE_MODE); + Set whitelist = getParserConfig().get(JSONLDSettings.WHITELIST); + boolean documentLoaderCache = getParserConfig().get(JSONLDSettings.DOCUMENT_LOADER_CACHE); JsonLdOptions opts = new JsonLdOptions(); opts.setUriValidation(false); @@ -144,8 +149,13 @@ private void parse(InputStream in, Reader reader, String baseURI) Document context = getParserConfig().get(JSONLDSettings.EXPAND_CONTEXT); DocumentLoader defaultDocumentLoader = opts.getDocumentLoader(); - CachingDocumentLoader cachingDocumentLoader = new CachingDocumentLoader(secureMode, whitelist, - documentLoaderCache); + + DocumentLoader documentLoader; + if (getParserConfig().get(JSONLDSettings.DOCUMENT_LOADER) == null) { + documentLoader = new CachingDocumentLoader(secureMode, whitelist, documentLoaderCache); + } else { + documentLoader = getParserConfig().get(JSONLDSettings.DOCUMENT_LOADER); + } if (context != null) { @@ -162,14 +172,14 @@ private void parse(InputStream in, Reader reader, String baseURI) return context; } - return cachingDocumentLoader.loadDocument(uri, options); + return documentLoader.loadDocument(uri, options); }); } } - if (secureMode && opts.getDocumentLoader() == defaultDocumentLoader) { - opts.setDocumentLoader(cachingDocumentLoader); + if (opts.getDocumentLoader() == defaultDocumentLoader) { + opts.setDocumentLoader(documentLoader); } if (baseURI != null && !baseURI.isEmpty()) { diff --git a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDSettings.java b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDSettings.java new file mode 100644 index 00000000000..d7774158959 --- /dev/null +++ b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDSettings.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * + * 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.rio.jsonld; + +import org.eclipse.rdf4j.rio.RioSetting; +import org.eclipse.rdf4j.rio.helpers.BooleanRioSetting; +import org.eclipse.rdf4j.rio.helpers.ClassRioSetting; +import org.eclipse.rdf4j.rio.helpers.RioSettingImpl; +import org.eclipse.rdf4j.rio.helpers.SetRioSetting; + +import no.hasmac.jsonld.document.Document; +import no.hasmac.jsonld.loader.DocumentLoader; + +/** + * Settings that can be passed to JSONLD Parsers and Writers. + * + * @author Peter Ansell + * @see JSONLD Data Structures + */ +public class JSONLDSettings { + + /** + * If set to true, the JSON-LD processor replaces arrays with just one element with that element during compaction. + * If set to false, all arrays will remain arrays even if they have just one element. + *

+ * Defaults to true. + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.compact_arrays}. + * + * @see JSONLD Data Structures + * + */ + public static final BooleanRioSetting COMPACT_ARRAYS = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.compact_arrays", "Compact arrays", Boolean.TRUE); + + /** + * If specified, it is used to retrieve remote documents and contexts; otherwise the processor's built-in loader is + * used. + * + */ + public static final RioSetting DOCUMENT_LOADER = new ClassRioSetting<>( + "org.eclipse.rdf4j.rio.jsonld.document_loader", "Document loader", null); + + /** + * The JSON-LD context to use when expanding JSON-LD + * + * @see https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-expandcontext. + */ + public static final RioSetting EXPAND_CONTEXT = new ClassRioSetting<>( + "org.eclipse.rdf4j.rio.jsonld.expand_context", + "A no.hasmac.jsonld.document.Document that contains the expanded context as specified in https://www.w3.org/TR/json-ld11-api/#dom-jsonldoptions-expandcontext", + null); + + public static final RioSetting FRAME = new ClassRioSetting<>( + "org.eclipse.rdf4j.rio.jsonld.frame_document", + "A no.hasmac.jsonld.document.Document that contains the frame used for framing as specified in https://www.w3.org/TR/json-ld11-framing/", + null);; + + /** + * The JSON-LD processor will throw an exception if a warning is encountered during processing. + * + */ + public static final BooleanRioSetting EXCEPTION_ON_WARNING = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.exception_on_warning", + "Throw an exception when logging a warning.", + Boolean.FALSE); + + /** + * If set to true, the JSON-LD processor is allowed to optimize the output of the + * Compaction algorithm to produce + * even compacter representations. + *

+ * Defaults to false. + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.optimize}. + * + * @see JSONLD Data Structures + * + */ + public static final BooleanRioSetting OPTIMIZE = new BooleanRioSetting("org.eclipse.rdf4j.rio.jsonld.optimize", + "Optimize output", Boolean.FALSE); + + /** + * If set to true, the JSON-LD processor may emit blank nodes for triple predicates, otherwise they will be omitted. + *

+ * Note: the use of blank node identifiers to label properties is obsolete, and may be removed in a future version + * of JSON-LD, + *

+ * Defaults to false. + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.produce_generalized_rdf}. + * + * @see JSONLD Data Structures + * + */ + public static final BooleanRioSetting PRODUCE_GENERALIZED_RDF = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.produce_generalized_rdf", "Produce generalized RDF", Boolean.FALSE); + + /** + * If set to true, the JSON-LD processor will try to convert typed values to JSON native types instead of using the + * expanded object form when converting from RDF. xsd:boolean values will be converted to true or false. xsd:integer + * and xsd:double values will be converted to JSON numbers. + *

+ * Defaults to false for RDF compatibility. + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.use_native_types}. + * + * @see JSONLD Data Structures + * + */ + public static final BooleanRioSetting USE_NATIVE_TYPES = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.use_native_types", "Use Native JSON Types", Boolean.FALSE); + + /** + * If set to true, the JSON-LD processor will use the expanded rdf:type IRI as the property instead of @type when + * converting from RDF. + *

+ * Defaults to false. + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.use_rdf_type}. + * + * @see JSONLD Data Structures + * + */ + public static final BooleanRioSetting USE_RDF_TYPE = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.use_rdf_type", "Use RDF Type", Boolean.FALSE); + + /** + * The {@link JSONLDMode} that the writer will use to reorganise the JSONLD document after it is created. + *

+ * Defaults to {@link JSONLDMode#EXPAND} to provide maximum RDF compatibility. + * + * @see JSONLD Features + * + */ + public static final RioSetting JSONLD_MODE = new RioSettingImpl<>( + "org.eclipse.rdf4j.rio.jsonld_mode", "JSONLD Mode", JSONLDMode.EXPAND); + + /** + * If set to true, the JSON-LD processor will try to represent the JSON-LD object in a hierarchical view. + *

+ * Default to false + *

+ * Can be overridden by setting system property {@code org.eclipse.rdf4j.rio.jsonld.hierarchical_view}. + * + */ + public static final BooleanRioSetting HIERARCHICAL_VIEW = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld.hierarchical_view", "Hierarchical representation of the JSON", Boolean.FALSE); + + /** + * Whitelist of remote/local resources that the JSON-LD parser can retrieve. Set of URIs as strings. This can be + * overridden by setting a system property with the key {@code org.eclipse.rdf4j.rio.jsonld_whitelist} and a JSON + * array of the desired values. + *

+ * Default: + * {@code Set.of("http://www.w3.org/ns/anno.jsonld", "https://www.w3.org/ns/anno.jsonld", "http://www.w3.org/ns/anno", "https://www.w3.org/ns/anno", "http://www.w3.org/ns/activitystreams.jsonld", "https://www.w3.org/ns/activitystreams.jsonld", "http://www.w3.org/ns/activitystreams", "https://www.w3.org/ns/activitystreams", "http://www.w3.org/ns/ldp.jsonld", "https://www.w3.org/ns/ldp.jsonld", "http://www.w3.org/ns/ldp", "https://www.w3.org/ns/ldp", "http://www.w3.org/ns/oa.jsonld", "https://www.w3.org/ns/oa.jsonld", "http://www.w3.org/ns/oa", "https://www.w3.org/ns/oa", "http://www.w3.org/ns/hydra/context.jsonld", "https://www.w3.org/ns/hydra/context.jsonld", "http://www.w3.org/ns/hydra/context", "https://www.w3.org/ns/hydra/context", "http://www.w3.org/2018/credentials/v1.jsonld", "https://www.w3.org/2018/credentials/v1.jsonld", "http://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/v1", "http://www.w3.org/2019/wot/td/v1.jsonld", "https://www.w3.org/2019/wot/td/v1.jsonld", "http://www.w3.org/2019/wot/td/v1", "https://www.w3.org/2019/wot/td/v1", "http://w3c.github.io/json-ld-rc/context.jsonld", "https://w3c.github.io/json-ld-rc/context.jsonld", "http://schema.org/", "https://schema.org/", "http://health-lifesci.schema.org/", "https://health-lifesci.schema.org/", "http://auto.schema.org/", "https://auto.schema.org/", "http://bib.schema.org/", "https://bib.schema.org/", "http://pending.schema.org/", "https://pending.schema.org/", "http://schema.org/docs/jsonldcontext.jsonld", "https://schema.org/docs/jsonldcontext.jsonld", "http://schema.org/version/latest/schemaorg-current-https.jsonld", "https://schema.org/version/latest/schemaorg-current-https.jsonld", "http://schema.org/version/latest/schemaorg-all-http.jsonld", "https://schema.org/version/latest/schemaorg-all-http.jsonld", "http://schema.org/version/latest/schemaorg-all-https.jsonld", "https://schema.org/version/latest/schemaorg-all-https.jsonld", "http://schema.org/version/latest/schemaorg-current-http.jsonld", "https://schema.org/version/latest/schemaorg-current-http.jsonld", "http://schema.org/version/latest/schemaorg-all.jsonld", "https://schema.org/version/latest/schemaorg-all.jsonld", "http://schema.org/version/latest/schemaorg-current.jsonld", "https://schema.org/version/latest/schemaorg-current.jsonld", "http://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "https://project-open-data.cio.gov/v1.1/schema/catalog.jsonld", "http://geojson.org/geojson-ld/geojson-context.jsonld", "https://geojson.org/geojson-ld/geojson-context.jsonld", "http://w3id.org/security/v1", "https://w3id.org/security/v1", "http://xmlns.com/foaf/spec/index.jsonld", "https://xmlns.com/foaf/spec/index.jsonld", "http://xmlns.com/foaf/spec/", "https://xmlns.com/foaf/spec/")} + * + */ + public static final SetRioSetting WHITELIST = new SetRioSetting<>( + "org.eclipse.rdf4j.rio.jsonld_whitelist", + "Whitelist of remote/local resources that the JSON-LD parser can retrieve. Set of URIs as strings.", + org.eclipse.rdf4j.rio.helpers.JSONLDSettings.WHITELIST.getDefaultValue() + ); + + /** + * Secure mode only allows loading remote/local resources (ex. context from url) that are whitelisted. This can be + * overridden by setting a system property with the key {@code org.eclipse.rdf4j.rio.jsonld_secure_mode} and a + * boolean value. + *

+ * Default: true + */ + public static final BooleanRioSetting SECURE_MODE = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld_secure_mode", + "Secure mode only allows loading remote/local resources (ex. context from url) that are whitelisted.", + Boolean.TRUE); + + /** + * The document loader cache is enabled by default. All loaded documents, such as remote contexts, are cached for 1 + * hour, or until the cache is full. The cache holds up to 1000 documents. The cache is shared between all + * JSONLDParsers. The cache can be disabled by setting this value to false. + *

+ * Default: true + */ + public static final BooleanRioSetting DOCUMENT_LOADER_CACHE = new BooleanRioSetting( + "org.eclipse.rdf4j.rio.jsonld_document_loader_cache", + "The document loader cache is enabled by default. All loaded documents, such as remote contexts, are cached for 1 hour, or until the cache is full. The cache holds up to 1000 documents. The cache is shared between all JSONLDParsers. The cache can be disabled by setting this value to false.", + Boolean.TRUE); + + /** + * Private default constructor. + */ + private JSONLDSettings() { + } + +} diff --git a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriter.java b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriter.java index d55f6118412..5633a9c6fc6 100644 --- a/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriter.java +++ b/core/rio/jsonld/src/main/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriter.java @@ -42,8 +42,6 @@ import org.eclipse.rdf4j.rio.WriterConfig; import org.eclipse.rdf4j.rio.helpers.AbstractRDFWriter; import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; -import org.eclipse.rdf4j.rio.helpers.JSONLDMode; -import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; import org.eclipse.rdf4j.rio.helpers.StatementCollector; import com.github.jsonldjava.core.JsonLdConsts; @@ -252,7 +250,7 @@ public int size() { .useRdfType(writerConfig.get(JSONLDSettings.USE_RDF_TYPE)) .build(); - JSONLDMode mode = getWriterConfig().get(JSONLDSettings.JSONLD_MODE); + JSONLDMode mode = mapJsonLdMode(getWriterConfig().get(JSONLDSettings.JSONLD_MODE)); switch (mode) { case EXPAND: @@ -298,6 +296,16 @@ public int size() { } } + private JSONLDMode mapJsonLdMode(Object jsonldMode) { + if (jsonldMode instanceof JSONLDMode) { + return (JSONLDMode) jsonldMode; + } + if (jsonldMode instanceof org.eclipse.rdf4j.rio.helpers.JSONLDMode) { + return JSONLDMode.valueOf(jsonldMode.toString()); + } + throw new IllegalArgumentException("Unknown JSONLDMode: " + jsonldMode); + } + private static RdfNQuad toRdfNQuad(Statement statement) { return new RdfNQuadAdapter(statement); } @@ -398,6 +406,15 @@ public Collection> getSupportedSettings() { result.add(JSONLDSettings.USE_NATIVE_TYPES); result.add(JSONLDSettings.PRODUCE_GENERALIZED_RDF); result.add(JSONLDSettings.EXCEPTION_ON_WARNING); + result.add(JSONLDSettings.FRAME); + + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.COMPACT_ARRAYS); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.JSONLD_MODE); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.USE_RDF_TYPE); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.USE_NATIVE_TYPES); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.PRODUCE_GENERALIZED_RDF); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.EXCEPTION_ON_WARNING); + result.add(org.eclipse.rdf4j.rio.helpers.JSONLDSettings.FRAME); return result; } diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomOldTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomOldTest.java new file mode 100644 index 00000000000..6a2cdcd012a --- /dev/null +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomOldTest.java @@ -0,0 +1,375 @@ +/******************************************************************************* + * Copyright (c) 2018 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.rio.jsonld; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.SECURE_MODE; +import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.WHITELIST; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.StringReader; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.io.FileUtils; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.model.vocabulary.XSD; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.helpers.ContextStatementCollector; +import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; +import org.eclipse.rdf4j.rio.helpers.ParseErrorCollector; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +import jakarta.json.spi.JsonProvider; +import no.hasmac.jsonld.document.Document; +import no.hasmac.jsonld.document.JsonDocument; + +/** + * Custom (non-manifest) tests for JSON-LD parser. + * + * Tests with the old JSONLDSettings class + * + * @author Peter Ansell + */ +public class JSONLDParserCustomOldTest { + + /** + * Backslash escaped "h" in "http" + */ + private static final String BACKSLASH_ESCAPED_TEST_STRING = "[{\"@id\": \"\\http://example.com/Subj1\",\"http://example.com/prop1\": [{\"@id\": \"http://example.com/Obj1\"}]}]"; + + /** + * Java/C++ style comments + */ + private static final String COMMENTS_TEST_STRING = "[{/*This is a non-standard java/c++ style comment\n*/\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": [{\"@id\": \"http://example.com/Obj1\"}]}]"; + + /** + * Tests for NaN + */ + private static final String NON_NUMERIC_NUMBERS_TEST_STRING = "[{\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": NaN}]"; + + /** + * Tests for numeric leading zeroes + */ + private static final String NUMERIC_LEADING_ZEROES_TEST_STRING = "[{\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": 000042}]"; + + /** + * Tests for single-quotes + */ + private static final String SINGLE_QUOTES_TEST_STRING = "[{\'@id\': \"http://example.com/Subj1\",\'http://example.com/prop1\': 42}]"; + + /** + * Tests for unquoted control char + */ + private static final String UNQUOTED_CONTROL_CHARS_TEST_STRING = "[{\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": \"42\u0009\"}]"; + + /** + * Tests for unquoted field names + */ + private static final String UNQUOTED_FIELD_NAMES_TEST_STRING = "[{@id: \"http://example.com/Subj1\",\"http://example.com/prop1\": 42}]"; + + /** + * YAML style comments + */ + private static final String YAML_COMMENTS_TEST_STRING = "[\n{#This is a non-standard yaml style comment/*\n\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": [{\"@id\": \"http://example.com/Obj1\"}]}]"; + + /** + * Trailing comma + */ + private static final String TRAILING_COMMA_TEST_STRING = "[{\"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": [{\"@id\": \"http://example.com/Obj1\"},]}]"; + + /** + * Strict duplicate detection + */ + private static final String STRICT_DUPLICATE_DETECTION_TEST_STRING = "[{\"@context\": {}, \"@context\": {}, \"@id\": \"http://example.com/Subj1\",\"http://example.com/prop1\": [{\"@id\": \"http://example.com/Obj1\"}]}]"; + + /** + * Used for custom document loader + */ + private static final String LOADER_CONTEXT = "{ \"@context\": {\"prop\": \"http://example.com/prop1\"} }"; + private static final String LOADER_JSONLD = "{ \"@context\": \"http://example.com/context.jsonld\", \"@id\": \"http://example.com/Subj1\", \"prop\": \"Property\" }"; + + private RDFParser parser; + + private ParseErrorCollector errors; + + private Model model; + + private final SimpleValueFactory F = SimpleValueFactory.getInstance(); + + private final IRI testSubjectIRI = F.createIRI("http://example.com/Subj1"); + private final IRI testPredicate = F.createIRI("http://example.com/prop1"); + private final IRI testObjectIRI = F.createIRI("http://example.com/Obj1"); + + private final Literal testObjectLiteralNotANumber = F.createLiteral("NaN", XSD.DOUBLE); + private final Literal testObjectLiteralNumber = F.createLiteral("42", XSD.INTEGER); + private final Literal testObjectLiteralUnquotedControlChar = F.createLiteral("42\u0009", XSD.STRING); + + @BeforeEach + public void setUp() { + parser = Rio.createParser(RDFFormat.JSONLD); + errors = new ParseErrorCollector(); + model = new LinkedHashModel(); + parser.setParseErrorListener(errors); + parser.setRDFHandler(new ContextStatementCollector(model, F)); + } + + private void verifyParseResults(Resource nextSubject, IRI nextPredicate, Value nextObject) { + assertEquals(0, errors.getWarnings().size()); + assertEquals(0, errors.getErrors().size()); + assertEquals(0, errors.getFatalErrors().size()); + + assertEquals(1, model.size()); + assertTrue(model.contains(nextSubject, nextPredicate, nextObject), + "model was not as expected: " + model.toString()); + } + + @Test + public void testSupportedSettings() { + assertEquals(19, parser.getSupportedSettings().size()); + } + + @Test + public void testAllowBackslashEscapingAnyCharacterDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(BACKSLASH_ESCAPED_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowBackslashEscapingAnyCharacterDisabled() { + assertThatThrownBy(() -> parser.parse(new StringReader(BACKSLASH_ESCAPED_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + + } + + @Test + public void testAllowCommentsDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(COMMENTS_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowNonNumericNumbersDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(NON_NUMERIC_NUMBERS_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowNumericLeadingZeroesDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(NUMERIC_LEADING_ZEROES_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowSingleQuotesDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(SINGLE_QUOTES_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowUnquotedControlCharactersDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(UNQUOTED_CONTROL_CHARS_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowUnquotedFieldNamesDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(UNQUOTED_FIELD_NAMES_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowYamlCommentsDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(YAML_COMMENTS_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testAllowTrailingCommaDefault() { + assertThatThrownBy(() -> parser.parse(new StringReader(TRAILING_COMMA_TEST_STRING), "")) + .isInstanceOf(RDFParseException.class) + .hasMessageContaining("Could not parse JSONLD"); + } + + @Test + public void testStrictDuplicateDetectionDefault() throws Exception { + parser.parse(new StringReader(STRICT_DUPLICATE_DETECTION_TEST_STRING), ""); + verifyParseResults(testSubjectIRI, testPredicate, testObjectIRI); + } + + @Test + public void testContext() throws Exception { + + Document jsonDocument = JsonDocument.of(new StringReader(LOADER_CONTEXT)); + jsonDocument.setDocumentUrl(URI.create("http://example.com/context.jsonld")); + + parser.getParserConfig().set(JSONLDSettings.EXPAND_CONTEXT, jsonDocument); + parser.parse(new StringReader(LOADER_JSONLD), ""); + assertTrue(model.predicates().contains(testPredicate)); + } + + @Test + public void testLocalFileSecurity() throws Exception { + + String contextUri = JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString(); + + String jsonld = FileUtils + .readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8) + .replace("file:./context.jsonld", contextUri); + + // expect exception + RDFParseException rdfParseException = Assertions.assertThrowsExactly(RDFParseException.class, () -> { + parser.parse(new StringReader(jsonld), ""); + }); + + Assertions.assertEquals("Could not load document from " + contextUri + + " because it is not whitelisted. See: JSONLDSettings.WHITELIST and JSONLDSettings.SECURE_MODE which can also be set as system properties.", + rdfParseException.getMessage()); + } + + @Test + public void testLocalFileSecurityWhiteList() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + String contextUri = JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString(); + jsonld = jsonld.replace("file:./context.jsonld", contextUri); + + parser.getParserConfig().set(WHITELIST, Set.of(contextUri)); + + parser.parse(new StringReader(jsonld), ""); + assertTrue(model.objects().contains(FOAF.PERSON)); + } + + @Test + public void testLocalFileSecurityDisableSecurity() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + jsonld = jsonld.replace("file:./context.jsonld", + JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString()); + + parser.getParserConfig().set(SECURE_MODE, false); + + parser.parse(new StringReader(jsonld), ""); + assertTrue(model.objects().contains(FOAF.PERSON)); + } + + @Test + public void testLocalFileSecurityDisableSecuritySystemProperty() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + jsonld = jsonld.replace("file:./context.jsonld", + JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString()); + + try { + System.setProperty(SECURE_MODE.getKey(), "false"); + parser.parse(new StringReader(jsonld), ""); + assertTrue(model.objects().contains(FOAF.PERSON)); + } finally { + System.clearProperty(SECURE_MODE.getKey()); + } + + } + + @RepeatedTest(10) + public void testRemoteContext() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/remoteContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + + parser.getParserConfig().set(WHITELIST, Set.of("https://schema.org")); + parser.parse(new StringReader(jsonld), ""); + assertEquals(59, model.size()); + } + + @Test + public void testRemoteContextSystemProperty() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/remoteContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + + try { + System.setProperty(WHITELIST.getKey(), "[\"https://schema.org\"]"); + parser.parse(new StringReader(jsonld), ""); + assertEquals(59, model.size()); + } finally { + System.clearProperty(WHITELIST.getKey()); + } + + } + + @Test + public void testRemoteContextException() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomOldTest.class.getClassLoader() + .getResource("testcases/jsonld/remoteContextException/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + + parser.getParserConfig().set(WHITELIST, Set.of("https://example.org/context.jsonld")); + RDFParseException rdfParseException = Assertions.assertThrowsExactly(RDFParseException.class, () -> { + parser.parse(new StringReader(jsonld), ""); + }); + + assertEquals("Could not load document from https://example.org/context.jsonld", rdfParseException.getMessage()); + } + + @Test + public void testSPI() { + ServiceLoader load = ServiceLoader.load(JsonProvider.class); + List collect = load.stream() + .map(ServiceLoader.Provider::get) + .map(t -> t.getClass().getName()) + .collect(Collectors.toList()); + assertFalse(collect.isEmpty()); + assertEquals("org.glassfish.json.JsonProviderImpl", collect.stream().findFirst().orElse("")); + } + +} diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomTest.java index f0fb28e05fe..0d36fbc0e4b 100644 --- a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomTest.java +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDParserCustomTest.java @@ -11,8 +11,6 @@ package org.eclipse.rdf4j.rio.jsonld; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.SECURE_MODE; -import static org.eclipse.rdf4j.rio.helpers.JSONLDSettings.WHITELIST; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -24,6 +22,7 @@ import java.util.List; import java.util.ServiceLoader; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; @@ -41,7 +40,6 @@ import org.eclipse.rdf4j.rio.RDFParser; import org.eclipse.rdf4j.rio.Rio; import org.eclipse.rdf4j.rio.helpers.ContextStatementCollector; -import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; import org.eclipse.rdf4j.rio.helpers.ParseErrorCollector; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -49,8 +47,12 @@ import org.junit.jupiter.api.Test; import jakarta.json.spi.JsonProvider; +import no.hasmac.jsonld.JsonLdError; import no.hasmac.jsonld.document.Document; import no.hasmac.jsonld.document.JsonDocument; +import no.hasmac.jsonld.loader.DocumentLoader; +import no.hasmac.jsonld.loader.DocumentLoaderOptions; +import no.hasmac.jsonld.loader.SchemeRouter; /** * Custom (non-manifest) tests for JSON-LD parser. @@ -152,7 +154,7 @@ private void verifyParseResults(Resource nextSubject, IRI nextPredicate, Value n @Test public void testSupportedSettings() { - assertEquals(15, parser.getSupportedSettings().size()); + assertEquals(19, parser.getSupportedSettings().size()); } @Test @@ -276,7 +278,7 @@ public void testLocalFileSecurityWhiteList() throws Exception { .toString(); jsonld = jsonld.replace("file:./context.jsonld", contextUri); - parser.getParserConfig().set(WHITELIST, Set.of(contextUri)); + parser.getParserConfig().set(JSONLDSettings.WHITELIST, Set.of(contextUri)); parser.parse(new StringReader(jsonld), ""); assertTrue(model.objects().contains(FOAF.PERSON)); @@ -292,12 +294,56 @@ public void testLocalFileSecurityDisableSecurity() throws Exception { .getResource("testcases/jsonld/localFileContext/context.jsonld") .toString()); - parser.getParserConfig().set(SECURE_MODE, false); + parser.getParserConfig().set(JSONLDSettings.SECURE_MODE, false); parser.parse(new StringReader(jsonld), ""); assertTrue(model.objects().contains(FOAF.PERSON)); } + @Test + public void testLocalFileSecurityCustomDocumentLoader() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + jsonld = jsonld.replace("file:./context.jsonld", + JSONLDParserCustomTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString()); + + AtomicBoolean called = new AtomicBoolean(false); + parser.getParserConfig().set(JSONLDSettings.DOCUMENT_LOADER, (url, options) -> { + called.set(true); + return new CachingDocumentLoader(false, Set.of(), true).loadDocument(url, options); + }); + + parser.parse(new StringReader(jsonld), ""); + assertTrue(model.objects().contains(FOAF.PERSON)); + assertTrue(called.get()); + } + + @Test + public void testLocalFileSecurityCustomDocumentLoader2() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + jsonld = jsonld.replace("file:./context.jsonld", + JSONLDParserCustomTest.class.getClassLoader() + .getResource("testcases/jsonld/localFileContext/context.jsonld") + .toString()); + + AtomicBoolean called = new AtomicBoolean(false); + parser.getParserConfig().set(JSONLDSettings.DOCUMENT_LOADER, (url, options) -> { + called.set(true); + return new CachingDocumentLoader(false, Set.of(), true).loadDocument(url, options); + }); + + parser.getParserConfig().set(JSONLDSettings.SECURE_MODE, false); + + parser.parse(new StringReader(jsonld), ""); + assertTrue(model.objects().contains(FOAF.PERSON)); + assertTrue(called.get()); + } + @Test public void testLocalFileSecurityDisableSecuritySystemProperty() throws Exception { String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomTest.class.getClassLoader() @@ -309,22 +355,32 @@ public void testLocalFileSecurityDisableSecuritySystemProperty() throws Exceptio .toString()); try { - System.setProperty(SECURE_MODE.getKey(), "false"); + System.setProperty(JSONLDSettings.SECURE_MODE.getKey(), "false"); parser.parse(new StringReader(jsonld), ""); assertTrue(model.objects().contains(FOAF.PERSON)); } finally { - System.clearProperty(SECURE_MODE.getKey()); + System.clearProperty(JSONLDSettings.SECURE_MODE.getKey()); } } - @RepeatedTest(10) + @RepeatedTest(100) + public void testRemoteContextDefaultWhitelist() throws Exception { + String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomTest.class.getClassLoader() + .getResource("testcases/jsonld/remoteContext/data.jsonld") + .getFile()), StandardCharsets.UTF_8); + + parser.parse(new StringReader(jsonld), ""); + assertEquals(59, model.size()); + } + + @RepeatedTest(100) public void testRemoteContext() throws Exception { String jsonld = FileUtils.readFileToString(new File(JSONLDParserCustomTest.class.getClassLoader() .getResource("testcases/jsonld/remoteContext/data.jsonld") .getFile()), StandardCharsets.UTF_8); - parser.getParserConfig().set(WHITELIST, Set.of("https://schema.org")); + parser.getParserConfig().set(JSONLDSettings.WHITELIST, Set.of("https://schema.org")); parser.parse(new StringReader(jsonld), ""); assertEquals(59, model.size()); } @@ -336,11 +392,12 @@ public void testRemoteContextSystemProperty() throws Exception { .getFile()), StandardCharsets.UTF_8); try { - System.setProperty(WHITELIST.getKey(), "[\"https://schema.org\"]"); + System.setProperty(JSONLDSettings.WHITELIST.getKey(), + "[\"https://schema.org\",\"https://example.org/context.jsonld\"]"); parser.parse(new StringReader(jsonld), ""); assertEquals(59, model.size()); } finally { - System.clearProperty(WHITELIST.getKey()); + System.clearProperty(JSONLDSettings.WHITELIST.getKey()); } } @@ -351,7 +408,7 @@ public void testRemoteContextException() throws Exception { .getResource("testcases/jsonld/remoteContextException/data.jsonld") .getFile()), StandardCharsets.UTF_8); - parser.getParserConfig().set(WHITELIST, Set.of("https://example.org/context.jsonld")); + parser.getParserConfig().set(JSONLDSettings.WHITELIST, Set.of("https://example.org/context.jsonld")); RDFParseException rdfParseException = Assertions.assertThrowsExactly(RDFParseException.class, () -> { parser.parse(new StringReader(jsonld), ""); }); diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterBackgroundTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterBackgroundTest.java index 3caeafc6488..daa70f68ae9 100644 --- a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterBackgroundTest.java +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterBackgroundTest.java @@ -16,6 +16,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.util.Collection; +import java.util.HashSet; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Literal; @@ -121,12 +123,14 @@ protected RioSetting[] getExpectedSupportedSettings() { return new RioSetting[] { BasicWriterSettings.BASE_DIRECTIVE, BasicWriterSettings.PRETTY_PRINT, - JSONLDSettings.COMPACT_ARRAYS, - JSONLDSettings.JSONLD_MODE, - JSONLDSettings.PRODUCE_GENERALIZED_RDF, - JSONLDSettings.USE_RDF_TYPE, - JSONLDSettings.USE_NATIVE_TYPES, - JSONLDSettings.EXCEPTION_ON_WARNING + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.COMPACT_ARRAYS, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.JSONLD_MODE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_RDF_TYPE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_NATIVE_TYPES, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.PRODUCE_GENERALIZED_RDF, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.EXCEPTION_ON_WARNING, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.FRAME + }; } } diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterOldTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterOldTest.java new file mode 100644 index 00000000000..263cd0eba25 --- /dev/null +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterOldTest.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others. + * + * 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.rio.jsonld; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.Model; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.impl.LinkedHashModel; +import org.eclipse.rdf4j.model.vocabulary.DCTERMS; +import org.eclipse.rdf4j.model.vocabulary.XSD; +import org.eclipse.rdf4j.rio.ParserConfig; +import org.eclipse.rdf4j.rio.RDFFormat; +import org.eclipse.rdf4j.rio.RDFHandlerException; +import org.eclipse.rdf4j.rio.RDFParseException; +import org.eclipse.rdf4j.rio.RDFParser; +import org.eclipse.rdf4j.rio.RDFWriter; +import org.eclipse.rdf4j.rio.RDFWriterTest; +import org.eclipse.rdf4j.rio.Rio; +import org.eclipse.rdf4j.rio.RioSetting; +import org.eclipse.rdf4j.rio.WriterConfig; +import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; +import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; +import org.eclipse.rdf4j.rio.helpers.JSONLDMode; +import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; +import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import no.hasmac.jsonld.JsonLdError; +import no.hasmac.jsonld.document.Document; +import no.hasmac.jsonld.document.JsonDocument; + +/** + * @author Peter Ansell + * + * Tests with the old JSONLDSettings class + */ +public class JSONLDWriterOldTest extends RDFWriterTest { + private final String exNs = "http://example.org/"; + + public JSONLDWriterOldTest() { + super(new JSONLDWriterFactory(), new JSONLDParserFactory()); + } + + @Override + protected void setupWriterConfig(WriterConfig config) { + super.setupWriterConfig(config); + config.set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + } + + @Override + protected void setupParserConfig(ParserConfig config) { + super.setupParserConfig(config); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, true); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES, true); + } + + @Test + @Override + @Disabled("TODO: Determine why this test is breaking") + public void testIllegalPrefix() throws RDFHandlerException, RDFParseException { + } + + @Test + public void testEmptyNamespace() { + IRI uri1 = vf.createIRI(exNs, "uri1"); + IRI uri2 = vf.createIRI(exNs, "uri2"); + + StringWriter w = new StringWriter(); + + RDFWriter rdfWriter = rdfWriterFactory.getWriter(w); + rdfWriter.getWriterConfig().set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + rdfWriter.startRDF(); + rdfWriter.handleNamespace("", exNs); + rdfWriter.handleNamespace(DCTERMS.PREFIX, DCTERMS.NAMESPACE); + rdfWriter.handleStatement(vf.createStatement(uri1, DCTERMS.TITLE, vf.createBNode())); + rdfWriter.handleStatement(vf.createStatement(uri1, uri2, vf.createBNode())); + rdfWriter.endRDF(); + + assertTrue(w.toString().contains("@vocab"), "Does not contain @vocab"); + } + + @Test + public void testRoundTripNamespaces() throws Exception { + IRI uri1 = vf.createIRI(exNs, "uri1"); + IRI uri2 = vf.createIRI(exNs, "uri2"); + Literal plainLit = vf.createLiteral("plain", XSD.STRING); + + Statement st1 = vf.createStatement(uri1, uri2, plainLit); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + RDFWriter rdfWriter = rdfWriterFactory.getWriter(out); + rdfWriter.getWriterConfig().set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + rdfWriter.startRDF(); + rdfWriter.handleNamespace("ex", exNs); + rdfWriter.handleStatement(st1); + rdfWriter.endRDF(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + RDFParser rdfParser = rdfParserFactory.getParser(); + ParserConfig config = new ParserConfig(); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, true); + config.set(BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES, true); + rdfParser.setParserConfig(config); + rdfParser.setValueFactory(vf); + Model model = new LinkedHashModel(); + rdfParser.setRDFHandler(new StatementCollector(model)); + + rdfParser.parse(in, "foo:bar"); + + assertEquals(1, model.size(), "Unexpected number of statements, found " + model.size()); + + assertTrue(model.contains(st1), "missing namespaced statement"); + + if (rdfParser.getRDFFormat().supportsNamespaces()) { + assertTrue(!model.getNamespaces().isEmpty(), + "Expected at least one namespace, found " + model.getNamespaces().size()); + assertEquals(exNs, model.getNamespace("ex").get().getName()); + } + } + + /** + * Test if the JSON-LD writer honors the "native RDF type" setting. + */ + @Test + public void testNativeRDFTypes() { + IRI subject = vf.createIRI(exNs, "uri1"); + IRI predicate = vf.createIRI(exNs, "uri2"); + Literal object = vf.createLiteral(true); + Statement stmt = vf.createStatement(subject, predicate, object); + + StringWriter w = new StringWriter(); + RDFWriter rdfWriter = rdfWriterFactory.getWriter(w); + rdfWriter.getWriterConfig().set(JSONLDSettings.JSONLD_MODE, JSONLDMode.COMPACT); + rdfWriter.getWriterConfig().set(JSONLDSettings.COMPACT_ARRAYS, true); + rdfWriter.getWriterConfig().set(JSONLDSettings.USE_NATIVE_TYPES, true); + + rdfWriter.startRDF(); + rdfWriter.handleStatement(stmt); + rdfWriter.endRDF(); + + assertTrue(!w.toString().contains("@type"), "Does contain @type"); + } + + @Test + public void testFraming() throws IOException, JsonLdError { + Model data = Rio.parse(new StringReader("{\n" + + " \"@context\": {\n" + + " \"dc11\": \"http://purl.org/dc/elements/1.1/\",\n" + + " \"ex\": \"http://example.org/vocab#\",\n" + + " \"xsd\": \"http://www.w3.org/2001/XMLSchema#\",\n" + + " \"ex:contains\": {\n" + + " \"@type\": \"@id\"\n" + + " }\n" + + " },\n" + + " \"@graph\": [\n" + + " {\n" + + " \"@id\": \"http://example.org/library\",\n" + + " \"@type\": \"ex:Library\",\n" + + " \"ex:contains\": \"http://example.org/library/the-republic\"\n" + + " },\n" + + " {\n" + + " \"@id\": \"http://example.org/library/the-republic\",\n" + + " \"@type\": \"ex:Book\",\n" + + " \"dc11:creator\": \"Plato\",\n" + + " \"dc11:title\": \"The Republic\",\n" + + " \"ex:contains\": \"http://example.org/library/the-republic#introduction\"\n" + + " },\n" + + " {\n" + + " \"@id\": \"http://example.org/library/the-republic#introduction\",\n" + + " \"@type\": \"ex:Chapter\",\n" + + " \"dc11:description\": \"An introductory chapter on The Republic.\",\n" + + " \"dc11:title\": \"The Introduction\"\n" + + " }\n" + + " ]\n" + + "}"), "", RDFFormat.JSONLD); + + Document frame = JsonDocument.of(new StringReader("{\n" + + " \"@context\": {\n" + + " \"dc11\": \"http://purl.org/dc/elements/1.1/\",\n" + + " \"ex\": \"http://example.org/vocab#\"\n" + + " },\n" + + " \"@type\": \"ex:Library\",\n" + + " \"ex:contains\": {\n" + + " \"@type\": \"ex:Book\",\n" + + " \"ex:contains\": {\n" + + " \"@type\": \"ex:Chapter\"\n" + + " }\n" + + " }\n" + + "}")); + + StringWriter stringWriter = new StringWriter(); + RDFWriter rdfWriter = rdfWriterFactory.getWriter(stringWriter); + rdfWriter.getWriterConfig().set(JSONLDSettings.JSONLD_MODE, JSONLDMode.FRAME); + rdfWriter.getWriterConfig().set(JSONLDSettings.FRAME, frame); + rdfWriter.getWriterConfig().set(BasicWriterSettings.PRETTY_PRINT, true); + + rdfWriter.startRDF(); + data.forEach(rdfWriter::handleStatement); + rdfWriter.endRDF(); + + assertEquals( + "{\n" + + " \"@id\": \"http://example.org/library\",\n" + + " \"@type\": \"ex:Library\",\n" + + " \"ex:contains\": {\n" + + " \"@id\": \"http://example.org/library/the-republic\",\n" + + " \"@type\": \"ex:Book\",\n" + + " \"ex:contains\": {\n" + + " \"@id\": \"http://example.org/library/the-republic#introduction\",\n" + + " \"@type\": \"ex:Chapter\",\n" + + " \"dc11:description\": \"An introductory chapter on The Republic.\",\n" + + " \"dc11:title\": \"The Introduction\"\n" + + " },\n" + + " \"dc11:creator\": \"Plato\",\n" + + " \"dc11:title\": \"The Republic\"\n" + + " },\n" + + " \"@context\": {\n" + + " \"dc11\": \"http://purl.org/dc/elements/1.1/\",\n" + + " \"ex\": \"http://example.org/vocab#\"\n" + + " }\n" + + "}", + stringWriter.toString()); + + } + + @Override + protected RioSetting[] getExpectedSupportedSettings() { + return new RioSetting[] { + BasicWriterSettings.BASE_DIRECTIVE, + BasicWriterSettings.PRETTY_PRINT, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.COMPACT_ARRAYS, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.JSONLD_MODE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_RDF_TYPE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_NATIVE_TYPES, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.PRODUCE_GENERALIZED_RDF, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.EXCEPTION_ON_WARNING, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.FRAME + }; + } +} diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java index 7eb23ffe413..0a904b5ab8e 100644 --- a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/jsonld/JSONLDWriterTest.java @@ -38,8 +38,6 @@ import org.eclipse.rdf4j.rio.WriterConfig; import org.eclipse.rdf4j.rio.helpers.BasicParserSettings; import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; -import org.eclipse.rdf4j.rio.helpers.JSONLDMode; -import org.eclipse.rdf4j.rio.helpers.JSONLDSettings; import org.eclipse.rdf4j.rio.helpers.StatementCollector; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -245,12 +243,13 @@ protected RioSetting[] getExpectedSupportedSettings() { return new RioSetting[] { BasicWriterSettings.BASE_DIRECTIVE, BasicWriterSettings.PRETTY_PRINT, - JSONLDSettings.COMPACT_ARRAYS, - JSONLDSettings.JSONLD_MODE, - JSONLDSettings.PRODUCE_GENERALIZED_RDF, - JSONLDSettings.USE_RDF_TYPE, - JSONLDSettings.USE_NATIVE_TYPES, - JSONLDSettings.EXCEPTION_ON_WARNING + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.COMPACT_ARRAYS, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.JSONLD_MODE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_RDF_TYPE, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.USE_NATIVE_TYPES, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.PRODUCE_GENERALIZED_RDF, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.EXCEPTION_ON_WARNING, + org.eclipse.rdf4j.rio.jsonld.JSONLDSettings.FRAME }; } } diff --git a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/ndjsonld/NDJSONLDWriterTest.java b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/ndjsonld/NDJSONLDWriterTest.java index 90c793e9ddd..eed20b0bb6f 100644 --- a/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/ndjsonld/NDJSONLDWriterTest.java +++ b/core/rio/jsonld/src/test/java/org/eclipse/rdf4j/rio/ndjsonld/NDJSONLDWriterTest.java @@ -58,7 +58,8 @@ protected RioSetting[] getExpectedSupportedSettings() { JSONLDSettings.PRODUCE_GENERALIZED_RDF, JSONLDSettings.USE_RDF_TYPE, JSONLDSettings.USE_NATIVE_TYPES, - JSONLDSettings.EXCEPTION_ON_WARNING + JSONLDSettings.EXCEPTION_ON_WARNING, + JSONLDSettings.FRAME }; } } diff --git a/core/rio/languages/pom.xml b/core/rio/languages/pom.xml index 6d671957f1f..b35931702bb 100644 --- a/core/rio/languages/pom.xml +++ b/core/rio/languages/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-languages RDF4J: Rio - Languages diff --git a/core/rio/n3/pom.xml b/core/rio/n3/pom.xml index 88783b054aa..54ae5fe573c 100644 --- a/core/rio/n3/pom.xml +++ b/core/rio/n3/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-n3 RDF4J: Rio - N3 (writer-only) diff --git a/core/rio/nquads/pom.xml b/core/rio/nquads/pom.xml index e0319824e58..044216524fb 100644 --- a/core/rio/nquads/pom.xml +++ b/core/rio/nquads/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-nquads RDF4J: Rio - N-Quads diff --git a/core/rio/ntriples/pom.xml b/core/rio/ntriples/pom.xml index dfb56bd96ba..37553504ed5 100644 --- a/core/rio/ntriples/pom.xml +++ b/core/rio/ntriples/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-ntriples RDF4J: Rio - N-Triples diff --git a/core/rio/pom.xml b/core/rio/pom.xml index d7f3720f3cc..77fc1cee292 100644 --- a/core/rio/pom.xml +++ b/core/rio/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio pom diff --git a/core/rio/rdfjson/pom.xml b/core/rio/rdfjson/pom.xml index f9dc87e07e5..55a3e3ad374 100644 --- a/core/rio/rdfjson/pom.xml +++ b/core/rio/rdfjson/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-rdfjson RDF4J: Rio - RDF/JSON diff --git a/core/rio/rdfxml/pom.xml b/core/rio/rdfxml/pom.xml index b035b9b2499..08a1e0f6eb3 100644 --- a/core/rio/rdfxml/pom.xml +++ b/core/rio/rdfxml/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-rdfxml RDF4J: Rio - RDF/XML diff --git a/core/rio/trig/pom.xml b/core/rio/trig/pom.xml index cdff54ce2dd..2736b12a916 100644 --- a/core/rio/trig/pom.xml +++ b/core/rio/trig/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-trig RDF4J: Rio - TriG diff --git a/core/rio/trix/pom.xml b/core/rio/trix/pom.xml index 8ddf9023a38..a8b99df7634 100644 --- a/core/rio/trix/pom.xml +++ b/core/rio/trix/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-trix RDF4J: Rio - TriX diff --git a/core/rio/turtle/pom.xml b/core/rio/turtle/pom.xml index 1d6259265fb..087f4221601 100644 --- a/core/rio/turtle/pom.xml +++ b/core/rio/turtle/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-rio - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-turtle RDF4J: Rio - Turtle diff --git a/core/sail/api/pom.xml b/core/sail/api/pom.xml index b454546a40d..94ba13deba0 100644 --- a/core/sail/api/pom.xml +++ b/core/sail/api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-api RDF4J: Sail API diff --git a/core/sail/base/pom.xml b/core/sail/base/pom.xml index 23d9cddb9bf..37f440d24a5 100644 --- a/core/sail/base/pom.xml +++ b/core/sail/base/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-base RDF4J: Sail base implementations diff --git a/core/sail/elasticsearch-store/pom.xml b/core/sail/elasticsearch-store/pom.xml index 1f3791f76c6..8542f4a1aaa 100644 --- a/core/sail/elasticsearch-store/pom.xml +++ b/core/sail/elasticsearch-store/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-elasticsearch-store RDF4J: Elasticsearch Store diff --git a/core/sail/elasticsearch/pom.xml b/core/sail/elasticsearch/pom.xml index dc30ae7b5f5..022319c4697 100644 --- a/core/sail/elasticsearch/pom.xml +++ b/core/sail/elasticsearch/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-elasticsearch RDF4J: Elastic Search Sail Index diff --git a/core/sail/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java b/core/sail/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java index 910c6eb385b..9373162dd79 100644 --- a/core/sail/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java +++ b/core/sail/elasticsearch/src/main/java/org/eclipse/rdf4j/sail/elasticsearch/ElasticsearchIndex.java @@ -87,14 +87,13 @@ /** * Requires an Elasticsearch cluster with the DeleteByQuery plugin. - * + *

* Note that, while RDF4J is licensed under the EDL, several ElasticSearch dependencies are licensed under the Elastic * license or the SSPL, which may have implications for some projects. - * + *

* Please consult the ElasticSearch website and license FAQ for more information. * * @see Elastic License FAQ - * * @see LuceneSail */ public class ElasticsearchIndex extends AbstractSearchIndex { @@ -409,13 +408,8 @@ protected SearchDocument getDocument(String id) throws IOException { @Override protected Iterable getDocuments(String resourceId) throws IOException { SearchHits hits = getDocuments(QueryBuilders.termQuery(SearchFields.URI_FIELD_NAME, resourceId)); - return Iterables.transform(hits, new Function<>() { - - @Override - public SearchDocument apply(SearchHit hit) { - return new ElasticsearchDocument(hit, geoContextMapper); - } - }); + return Iterables.transform(hits, + (Function) hit -> new ElasticsearchDocument(hit, geoContextMapper)); } @Override @@ -577,18 +571,26 @@ protected Iterable query(Resource subject, QuerySpec sp } SearchHits hits; - if (subject != null) { - hits = search(subject, request, qb); + + int numDocs; + + Integer specNumDocs = spec.getNumDocs(); + if (specNumDocs != null) { + if (specNumDocs < 0) { + throw new IllegalArgumentException("numDocs must be >= 0"); + } + numDocs = specNumDocs; } else { - hits = search(request, qb); + numDocs = -1; } - return Iterables.transform(hits, new Function<>() { - @Override - public DocumentScore apply(SearchHit hit) { - return new ElasticsearchDocumentScore(hit, geoContextMapper); - } - }); + if (subject != null) { + hits = search(subject, request, qb, numDocs); + } else { + hits = search(request, qb, numDocs); + } + return Iterables.transform(hits, + (Function) hit -> new ElasticsearchDocumentScore(hit, geoContextMapper)); } /** @@ -600,11 +602,24 @@ public DocumentScore apply(SearchHit hit) { * @return search hits */ public SearchHits search(Resource resource, SearchRequestBuilder request, QueryBuilder query) { + return search(resource, request, query, -1); + } + + /** + * Evaluates the given query only for the given resource. + * + * @param resource + * @param request + * @param query + * @param numDocs + * @return search hits + */ + public SearchHits search(Resource resource, SearchRequestBuilder request, QueryBuilder query, int numDocs) { // rewrite the query QueryBuilder idQuery = QueryBuilders.termQuery(SearchFields.URI_FIELD_NAME, SearchFields.getResourceID(resource)); QueryBuilder combinedQuery = QueryBuilders.boolQuery().must(idQuery).must(query); - return search(request, combinedQuery); + return search(request, combinedQuery, numDocs); } @Override @@ -686,13 +701,8 @@ protected Iterable geoRelationQuery(String relation, I SearchRequestBuilder request = client.prepareSearch(); SearchHits hits = search(request, QueryBuilders.boolQuery().must(qb).filter(fb)); - return Iterables.transform(hits, new Function<>() { - - @Override - public DocumentResult apply(SearchHit hit) { - return new ElasticsearchDocumentResult(hit, geoContextMapper); - } - }); + return Iterables.transform(hits, + (Function) hit -> new ElasticsearchDocumentResult(hit, geoContextMapper)); } private ShapeRelation toSpatialOp(String relation) { @@ -712,25 +722,43 @@ private ShapeRelation toSpatialOp(String relation) { * Evaluates the given query and returns the results as a TopDocs instance. */ public SearchHits search(SearchRequestBuilder request, QueryBuilder query) { + return search(request, query, -1); + } + + /** + * Evaluates the given query and returns the results as a TopDocs instance. + */ + public SearchHits search(SearchRequestBuilder request, QueryBuilder query, int numDocs) { String[] types = getTypes(); - int nDocs; - if (maxDocs > 0) { - nDocs = maxDocs; - } else { + + if (numDocs < -1) { + throw new IllegalArgumentException("numDocs should be 0 or greater if defined by the user"); + } + + int size = defaultNumDocs; + if (numDocs >= 0) { + // If the user has set numDocs we will use that. If it is 0 then the implementation may end up throwing an + // exception. + size = Math.min(maxDocs, numDocs); + } + + if (size < 0) { + // defaultNumDocs is not set long docCount = client.prepareSearch(indexName) .setTypes(types) .setSource(new SearchSourceBuilder().size(0).query(query)) .get() .getHits() .getTotalHits().value; - nDocs = Math.max((int) Math.min(docCount, Integer.MAX_VALUE), 1); + size = Math.max((int) Math.min(docCount, maxDocs), 1); } + SearchResponse response = request.setIndices(indexName) .setTypes(types) .setVersion(false) .seqNoAndPrimaryTerm(true) .setQuery(query) - .setSize(nDocs) + .setSize(size) .execute() .actionGet(); return response.getHits(); diff --git a/core/sail/extensible-store/pom.xml b/core/sail/extensible-store/pom.xml index 6103dcbbd53..e8d6a1af491 100644 --- a/core/sail/extensible-store/pom.xml +++ b/core/sail/extensible-store/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-extensible-store RDF4J: Extensible Store diff --git a/core/sail/inferencer/pom.xml b/core/sail/inferencer/pom.xml index 1f6ad930f5b..45babf4a3e2 100644 --- a/core/sail/inferencer/pom.xml +++ b/core/sail/inferencer/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-inferencer RDF4J: Inferencer Sails diff --git a/core/sail/lmdb/pom.xml b/core/sail/lmdb/pom.xml index 1486dab2eaf..9a494fe3521 100644 --- a/core/sail/lmdb/pom.xml +++ b/core/sail/lmdb/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-lmdb RDF4J: LmdbStore diff --git a/core/sail/lucene-api/pom.xml b/core/sail/lucene-api/pom.xml index 0f4def0ee74..a52d440fc00 100644 --- a/core/sail/lucene-api/pom.xml +++ b/core/sail/lucene-api/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-lucene-api RDF4J: Lucene Sail API diff --git a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java index d8f85a4ff58..ba3a7f3d35c 100644 --- a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java +++ b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/AbstractSearchIndex.java @@ -41,6 +41,7 @@ import org.eclipse.rdf4j.query.MalformedQueryException; import org.eclipse.rdf4j.query.algebra.Var; import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; +import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.lucene.util.MapOfListMaps; import org.locationtech.spatial4j.context.SpatialContext; @@ -65,7 +66,8 @@ public abstract class AbstractSearchIndex implements SearchIndex { REJECTED_DATATYPES.add("http://www.w3.org/2001/XMLSchema#float"); } - protected int maxDocs; + protected int defaultNumDocs = -1; + protected int maxDocs = Integer.MAX_VALUE; protected Set wktFields = Collections.singleton(SearchFields.getPropertyField(GEO.AS_WKT)); @@ -75,8 +77,29 @@ public abstract class AbstractSearchIndex implements SearchIndex { @Override public void initialize(Properties parameters) throws Exception { - String maxDocParam = parameters.getProperty(LuceneSail.MAX_DOCUMENTS_KEY); - maxDocs = (maxDocParam != null) ? Integer.parseInt(maxDocParam) : -1; + String maxDocumentsParam = parameters.getProperty(LuceneSail.MAX_DOCUMENTS_KEY); + String defaultNumDocsParam = parameters.getProperty(LuceneSail.DEFAULT_NUM_DOCS_KEY); + + if ((maxDocumentsParam != null)) { + maxDocs = Integer.parseInt(maxDocumentsParam); + + // if maxDocs is set then defaultNumDocs is set to maxDocs if it is not set, because we now have a known + // upper limit + defaultNumDocs = (defaultNumDocsParam != null) ? Math.min(maxDocs, Integer.parseInt(defaultNumDocsParam)) + : maxDocs; + } else { + // we can never return more than Integer.MAX_VALUE documents + maxDocs = Integer.MAX_VALUE; + + // legacy behaviour is to return the number of documents that the query would return if there was no limit, + // so if the defaultNumDocs is not set, we set it to -1 to signal that there is no limit + defaultNumDocs = (defaultNumDocsParam != null) ? Integer.parseInt(defaultNumDocsParam) : -1; + } + + if (defaultNumDocs > maxDocs) { + throw new IllegalArgumentException(LuceneSail.DEFAULT_NUM_DOCS_KEY + " must be less than or equal to " + + LuceneSail.MAX_DOCUMENTS_KEY + " (" + defaultNumDocs + " > " + maxDocs + ")"); + } String wktFieldParam = parameters.getProperty(LuceneSail.WKT_FIELDS); if (wktFieldParam != null) { @@ -146,7 +169,7 @@ public boolean accept(Literal literal) { // we reject literals that aren't in the list of the indexed lang if (indexedLangs != null - && (!literal.getLanguage().isPresent() + && (literal.getLanguage().isEmpty() || !indexedLangs.contains(literal.getLanguage().get().toLowerCase() ))) { return false; @@ -353,11 +376,8 @@ public final synchronized void addRemoveStatements(Collection added, // remove value from both property field and the // corresponding text field String field = SearchFields.getPropertyField(r.getPredicate()); - Set removedValues = removedOfResource.get(field); - if (removedValues == null) { - removedValues = new HashSet<>(); - removedOfResource.put(field, removedValues); - } + Set removedValues = removedOfResource.computeIfAbsent(field, + k -> new HashSet<>()); removedValues.add(val); } } @@ -545,7 +565,8 @@ private Iterable evaluateQuery(QuerySpec query) { hits = query(query.getSubject(), query); } } catch (Exception e) { - logger.error("There was a problem evaluating query '" + query.getCatQuery() + "'!", e); + logger.error("There was a problem evaluating query '{}'!", query.getCatQuery(), e); + assert false : "There was a problem evaluating query '" + query.getCatQuery() + "'!"; } return hits; @@ -717,6 +738,8 @@ private Iterable evaluateQuery(DistanceQuerySpec que } catch (Exception e) { logger.error("There was a problem evaluating distance query 'within " + distance + getUnitSymbol(units) + " of " + from.getLabel() + "'!", e); + assert false : "There was a problem evaluating distance query 'within " + distance + getUnitSymbol(units) + + " of " + from.getLabel() + "'!"; } return hits; @@ -825,6 +848,8 @@ private Iterable evaluateQuery(GeoRelationQuerySpec qu } catch (Exception e) { logger.error("There was a problem evaluating spatial relation query '" + query.getRelation() + " " + qgeom.getLabel() + "'!", e); + assert false : "There was a problem evaluating spatial relation query '" + query.getRelation() + " " + + qgeom.getLabel() + "'!"; } return hits; diff --git a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java index 37e6e8c0db8..f2d96ecc435 100644 --- a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java +++ b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSail.java @@ -290,10 +290,17 @@ public class LuceneSail extends NotifyingSailWrapper { public static final String LUCENE_RAMDIR_KEY = "useramdir"; /** - * Set the key "maxDocuments=<n>" as sail parameter to limit the maximum number of documents to return from a - * search query. The default is to return all documents. NB: this may involve extra cost for some SearchIndex + * Set the key "defaultNumDocs=<n>" as sail parameter to limit the maximum number of documents to return from + * a search query. The default is to return all documents. NB: this may involve extra cost for some SearchIndex * implementations as they may have to determine this number. */ + public static final String DEFAULT_NUM_DOCS_KEY = "defaultNumDocs"; + + /** + * Set the key "maxDocuments=<n>" as sail parameter to limit the maximum number of documents the user can + * query at a time to return from a search query. The default is the value of the {@link #DEFAULT_NUM_DOCS_KEY} + * parameter. + */ public static final String MAX_DOCUMENTS_KEY = "maxDocuments"; /** diff --git a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailSchema.java b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailSchema.java index 13e5d891818..78d56b24734 100644 --- a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailSchema.java +++ b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/LuceneSailSchema.java @@ -52,6 +52,8 @@ public class LuceneSailSchema { public static final IRI CONTEXT; + public static final IRI NUM_DOCS; + static { ValueFactory factory = SimpleValueFactory.getInstance(); // compatible with beta4: // creating a new factory @@ -73,5 +75,6 @@ public class LuceneSailSchema { WITHIN_DISTANCE = factory.createIRI(NAMESPACE + "withinDistance"); DISTANCE = factory.createIRI(NAMESPACE + "distance"); CONTEXT = factory.createIRI(NAMESPACE + "context"); + NUM_DOCS = factory.createIRI(NAMESPACE + "numDocs"); } } diff --git a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpec.java b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpec.java index c6886ccd084..0e647c592f7 100644 --- a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpec.java +++ b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpec.java @@ -16,7 +16,9 @@ import java.util.stream.Collectors; import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.query.algebra.QueryModelNode; import org.eclipse.rdf4j.query.algebra.SingletonSet; import org.eclipse.rdf4j.query.algebra.StatementPattern; @@ -67,21 +69,43 @@ private static void append(Var var, StringBuilder buffer) { private final StatementPattern idPattern; + private final StatementPattern numDocsPattern; + private final Resource subject; private final String matchesVarName; private final String scoreVarName; + private final Integer numDocs; + public QuerySpec(StatementPattern matchesPattern, Collection queryPatterns, StatementPattern scorePattern, StatementPattern typePattern, StatementPattern idPattern, Resource subject) { + this(matchesPattern, queryPatterns, scorePattern, typePattern, idPattern, null, subject); + } + + public QuerySpec(StatementPattern matchesPattern, Collection queryPatterns, + StatementPattern scorePattern, StatementPattern typePattern, + StatementPattern idPattern, StatementPattern numDocsPattern, Resource subject) { this.matchesPattern = matchesPattern; this.queryPatterns = queryPatterns; this.scorePattern = scorePattern; this.typePattern = typePattern; this.idPattern = idPattern; + this.numDocsPattern = numDocsPattern; this.subject = subject; + if (numDocsPattern != null) { + Value val = numDocsPattern.getObjectVar().getValue(); + if (val != null && val.isLiteral()) { + this.numDocs = ((Literal) val).intValue(); + } else { + throw new IllegalArgumentException("numDocs should be constant literal value"); + } + } else { + this.numDocs = null; + } + if (matchesPattern != null) { this.matchesVarName = matchesPattern.getSubjectVar().getName(); } else { @@ -101,9 +125,11 @@ public QuerySpec(String matchesVarName, String propertyVarName, String scoreVarN this.matchesPattern = null; this.scorePattern = null; this.typePattern = null; + this.numDocsPattern = null; this.queryPatterns = Set.of(); this.idPattern = null; this.subject = subject; + this.numDocs = null; } @Override @@ -121,6 +147,7 @@ public QueryModelNode removeQueryPatterns() { replace(getScorePattern(), replacement); replace(getTypePattern(), replacement); replace(getIdPattern(), replacement); + replace(getNumDocsPattern(), replacement); final QueryModelNode placeholder = new SingletonSet(); @@ -154,6 +181,10 @@ public StatementPattern getScorePattern() { return scorePattern; } + public StatementPattern getNumDocsPattern() { + return numDocsPattern; + } + /** * The variable name associated with the query score * @@ -163,6 +194,10 @@ public String getScoreVariableName() { return scoreVarName; } + public Integer getNumDocs() { + return numDocs; + } + public StatementPattern getTypePattern() { return typePattern; } diff --git a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java index c62a30266ab..73c88dc10f6 100644 --- a/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java +++ b/core/sail/lucene-api/src/main/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilder.java @@ -15,6 +15,7 @@ import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.INDEXID; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.LUCENE_QUERY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.MATCHES; +import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.NUM_DOCS; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.PROPERTY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.QUERY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.SCORE; @@ -152,7 +153,7 @@ public void process(TupleExpr tupleExpr, BindingSet bindings, Collection queryPatterns; try { @@ -161,6 +162,7 @@ public void process(TupleExpr tupleExpr, BindingSet bindings, Collection boostPatterns = new ArrayList<>(); + public ArrayList numDocsPatterns = new ArrayList<>(); + /** * Method implementing the visitor pattern that gathers all statements using a predicate from the LuceneSail's * namespace. @@ -487,6 +496,8 @@ public void meet(StatementPattern node) { idPatterns.add(node); } else if (BOOST.equals(predicate)) { boostPatterns.add(node); + } else if (NUM_DOCS.equals(predicate)) { + numDocsPatterns.add(node); } else if (TYPE.equals(predicate)) { Value object = node.getObjectVar().getValue(); if (LUCENE_QUERY.equals(object)) { diff --git a/core/sail/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java b/core/sail/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java index 89c474e0d44..d7009f4f909 100644 --- a/core/sail/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java +++ b/core/sail/lucene-api/src/test/java/org/eclipse/rdf4j/sail/lucene/QuerySpecBuilderTest.java @@ -14,6 +14,7 @@ import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.BOOST; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.LUCENE_QUERY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.MATCHES; +import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.NUM_DOCS; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.QUERY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.SCORE; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.SNIPPET; @@ -55,6 +56,7 @@ public void testQueryInterpretation() { "<" + TYPE + "> <" + LUCENE_QUERY + ">; " + "<" + QUERY + "> \"my Lucene query\"; " + "<" + SCORE + "> ?Score; " + + "<" + NUM_DOCS + "> 76; " + "<" + SNIPPET + "> ?Snippet ]. } "; ParsedQuery query = parser.parseQuery(buffer, null); TupleExpr tupleExpr = query.getTupleExpr(); @@ -69,6 +71,8 @@ public void testQueryInterpretation() { assertEquals("Score", querySpec.getScorePattern().getObjectVar().getName()); assertEquals("Snippet", param.getSnippetPattern().getObjectVar().getName()); assertEquals(LUCENE_QUERY, querySpec.getTypePattern().getObjectVar().getValue()); + assertEquals(76, querySpec.getNumDocs()); + assertEquals(76, ((Literal) querySpec.getNumDocsPattern().getObjectVar().getValue()).intValue()); assertEquals("my Lucene query", param.getQuery()); assertNull(querySpec.getSubject()); } @@ -80,11 +84,13 @@ public void testMultipleQueriesInterpretation() { "<" + TYPE + "> <" + LUCENE_QUERY + ">; " + "<" + QUERY + "> \"my Lucene query\"; " + "<" + SCORE + "> ?score1; " + + "<" + NUM_DOCS + "> 86; " + "<" + SNIPPET + "> ?snippet1 ]. " + " ?sub2 <" + MATCHES + "> [ " + "<" + TYPE + "> <" + LUCENE_QUERY + ">; " + "<" + QUERY + "> \"second lucene query\"; " + "<" + SCORE + "> ?score2; " + + "<" + NUM_DOCS + "> 13; " + "<" + SNIPPET + "> ?snippet2 ]. " + // and connect them both via any X in between, just as salt to make the // parser do something @@ -103,6 +109,7 @@ public void testMultipleQueriesInterpretation() { // Matched the first assertEquals("sub1", querySpec.getMatchesPattern().getSubjectVar().getName()); assertEquals(1, querySpec.getQueryPatterns().size()); + assertEquals(86, querySpec.getNumDocs()); QuerySpec.QueryParam param = querySpec.getQueryPatterns().iterator().next(); assertEquals("my Lucene query", ((Literal) param.getQueryPattern().getObjectVar().getValue()).getLabel()); @@ -116,6 +123,7 @@ public void testMultipleQueriesInterpretation() { // and the second assertEquals("sub2", querySpec.getMatchesPattern().getSubjectVar().getName()); assertEquals(1, querySpec.getQueryPatterns().size()); + assertEquals(13, querySpec.getNumDocs()); QuerySpec.QueryParam param = querySpec.getQueryPatterns().iterator().next(); assertEquals("second lucene query", ((Literal) param.getQueryPattern().getObjectVar().getValue()).getLabel()); diff --git a/core/sail/lucene/pom.xml b/core/sail/lucene/pom.xml index 0bf14bb2dc4..530c6ac3c5d 100644 --- a/core/sail/lucene/pom.xml +++ b/core/sail/lucene/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-lucene RDF4J: Lucene Sail Index diff --git a/core/sail/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/impl/LuceneIndex.java b/core/sail/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/impl/LuceneIndex.java index 42174324308..5999a91cbe8 100644 --- a/core/sail/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/impl/LuceneIndex.java +++ b/core/sail/lucene/src/main/java/org/eclipse/rdf4j/sail/lucene/impl/LuceneIndex.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -751,11 +752,23 @@ protected Iterable query(Resource subject, QuerySpec sp highlighter = null; } + int numDocs; + + Integer specNumDocs = spec.getNumDocs(); + if (specNumDocs != null) { + if (specNumDocs < 0) { + throw new IllegalArgumentException("numDocs must be >= 0"); + } + numDocs = specNumDocs; + } else { + numDocs = -1; + } + TopDocs docs; if (subject != null) { - docs = search(subject, q); + docs = search(subject, q, numDocs); } else { - docs = search(q); + docs = search(q, numDocs); } return Iterables.transform(Arrays.asList(docs.scoreDocs), (ScoreDoc doc) -> new LuceneDocumentScore(doc, highlighter, LuceneIndex.this)); @@ -960,12 +973,25 @@ public synchronized String getSnippet(String fieldName, String text, Highlighter * @throws IOException */ public synchronized TopDocs search(Resource resource, Query query) throws IOException { + return search(resource, query, -1); + } + + /** + * Evaluates the given query only for the given resource. + * + * @param resource + * @param query + * @param numDocs + * @return top documents + * @throws IOException + */ + public synchronized TopDocs search(Resource resource, Query query, int numDocs) throws IOException { // rewrite the query TermQuery idQuery = new TermQuery(new Term(SearchFields.URI_FIELD_NAME, SearchFields.getResourceID(resource))); BooleanQuery.Builder combinedQuery = new BooleanQuery.Builder(); combinedQuery.add(idQuery, Occur.MUST); combinedQuery.add(query, Occur.MUST); - return search(combinedQuery.build()); + return search(combinedQuery.build(), numDocs); } /** @@ -976,13 +1002,32 @@ public synchronized TopDocs search(Resource resource, Query query) throws IOExce * @throws IOException */ public synchronized TopDocs search(Query query) throws IOException { - int nDocs; - if (maxDocs > 0) { - nDocs = maxDocs; - } else { - nDocs = Math.max(getIndexReader().numDocs(), 1); + return search(query, -1); + } + + /** + * Evaluates the given query and returns the results as a TopDocs instance. + * + * @param query + * @param numDocs + * @return top documents + * @throws IOException + */ + public synchronized TopDocs search(Query query, int numDocs) throws IOException { + if (numDocs < -1) { + throw new IllegalArgumentException("numDocs should be 0 or greater if defined by the user"); + } + + int size = defaultNumDocs; + if (numDocs >= 0) { + // If the user has set numDocs we will use that. If it is 0 then the implementation may end up throwing an + // exception. + size = Math.min(maxDocs, numDocs); + } + if (size < 0) { + size = Math.max(getIndexReader().numDocs(), 1); } - return getIndexSearcher().search(query, nDocs); + return getIndexSearcher().search(query, size); } private QueryParser getQueryParser(IRI propertyURI) { diff --git a/core/sail/memory/pom.xml b/core/sail/memory/pom.xml index ec77c2ff18d..ae81a8c5531 100644 --- a/core/sail/memory/pom.xml +++ b/core/sail/memory/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-memory RDF4J: MemoryStore diff --git a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/QueryPlanRetrievalTest.java b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/QueryPlanRetrievalTest.java index 137a46c4059..187e7eb0e75 100644 --- a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/QueryPlanRetrievalTest.java +++ b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/QueryPlanRetrievalTest.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; @@ -85,7 +86,7 @@ public class QueryPlanRetrievalTest { "\n" + "\n" + " {\n" + - " SELECT DISTINCT ?buyerrole ?countryID WHERE {\n" + + " SELECT DISTINCT ?buyerrole ?countryID WHERE {\n" + " ?org epo:hasBuyerType ?buytype .\n" + " FILTER (?buytype != )\n" + @@ -1153,4 +1154,174 @@ public void testArbitraryLengthPath() { } + @Test + public void testHaving() { + + String expected = "Order (resultSizeActual=4)\n" + + " OrderElem (ASC)\n" + + " Var (name=nbTerm)\n" + + " OrderElem (ASC)\n" + + " Var (name=nameSjb1)\n" + + " OrderElem (ASC)\n" + + " Var (name=idTerm3)\n" + + " Projection (resultSizeActual=4)\n" + + " ├── ProjectionElemList\n" + + " │ ProjectionElem \"nameSjb1\"\n" + + " │ ProjectionElem \"idCN1\"\n" + + " │ ProjectionElem \"nbTerm\"\n" + + " │ ProjectionElem \"idTerm3\"\n" + + " └── Join (JoinIterator) (resultSizeActual=4)\n" + + " ╠══ Projection (new scope) (resultSizeActual=2) [left]\n" + + " ║ ├── ProjectionElemList\n" + + " ║ │ ProjectionElem \"nameSjb1\"\n" + + " ║ │ ProjectionElem \"idCN1\"\n" + + " ║ │ ProjectionElem \"nbTerm\"\n" + + " ║ └── Extension (resultSizeActual=2)\n" + + " ║ ╠══ Extension (resultSizeActual=2)\n" + + " ║ ║ Filter (resultSizeActual=2)\n" + + " ║ ║ ╠══ Compare (<)\n" + + " ║ ║ ║ Var (name=nbTerm)\n" + + " ║ ║ ║ ValueConstant (value=\"3\"^^)\n" + + " ║ ║ ╚══ Group (nameSjb1, idCN1) (resultSizeActual=4)\n" + + " ║ ║ ├── LeftJoin (LeftJoinIterator) (resultSizeActual=11)\n" + + " ║ ║ │ ╠══ Join (JoinIterator) (resultSizeActual=11) [left]\n" + + " ║ ║ │ ║ ├── StatementPattern (costEstimate=54, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n" + + + " ║ ║ │ ║ │ s: Var (name=idTerm1)\n" + + " ║ ║ │ ║ │ p: Var (name=_const_c6e40399_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConductingEquipment, anonymous)\n" + + + " ║ ║ │ ║ │ o: Var (name=idSjb1)\n" + + " ║ ║ │ ║ └── Join (JoinIterator) (resultSizeActual=11) [right]\n" + + " ║ ║ │ ║ ╠══ StatementPattern (costEstimate=1.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n" + + + " ║ ║ │ ║ ║ s: Var (name=idSjb1)\n" + + " ║ ║ │ ║ ║ p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n" + + + " ║ ║ │ ║ ║ o: Var (name=_const_6965b017_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#BusbarSection, anonymous)\n" + + + " ║ ║ │ ║ ╚══ Join (JoinIterator) (resultSizeActual=11) [right]\n" + + " ║ ║ │ ║ ├── StatementPattern (costEstimate=2.12, resultSizeEstimate=13, resultSizeActual=4) [left]\n" + + + " ║ ║ │ ║ │ s: Var (name=idTerm1)\n" + + " ║ ║ │ ║ │ p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" + + + " ║ ║ │ ║ │ o: Var (name=idCN1)\n" + + " ║ ║ │ ║ └── StatementPattern (costEstimate=4.24, resultSizeEstimate=13, resultSizeActual=11) [right]\n" + + + " ║ ║ │ ║ s: Var (name=idTermOfCN)\n" + + " ║ ║ │ ║ p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" + + + " ║ ║ │ ║ o: Var (name=idCN1)\n" + + " ║ ║ │ ╚══ StatementPattern (resultSizeEstimate=4.00, resultSizeActual=11) [right]\n" + + + " ║ ║ │ s: Var (name=idSjb1)\n" + + " ║ ║ │ p: Var (name=_const_857da984_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#IdentifiedObject.name, anonymous)\n" + + + " ║ ║ │ o: Var (name=nameSjb1)\n" + + " ║ ║ └── GroupElem (nbTerm)\n" + + " ║ ║ Count\n" + + " ║ ║ Var (name=idTermOfCN)\n" + + " ║ ╚══ ExtensionElem (nbTerm)\n" + + " ║ Count\n" + + " ║ Var (name=idTermOfCN)\n" + + " ╚══ StatementPattern (costEstimate=18, resultSizeEstimate=13, resultSizeActual=4) [right]\n" + + " s: Var (name=idTerm3)\n" + + " p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n" + + + " o: Var (name=idCN1)\n"; + SailRepository sailRepository = new SailRepository(new MemoryStore()); + + try (SailRepositoryConnection connection = sailRepository.getConnection()) { + connection.add(new StringReader("@prefix rdf: .\n" + + "@prefix cim: .\n" + + "@prefix : .\n" + + "\n" + + "# Busbar Sections\n" + + ":BusbarSection1 rdf:type cim:BusbarSection ;\n" + + " cim:IdentifiedObject.name \"Busbar1\" .\n" + + "\n" + + ":BusbarSection2 rdf:type cim:BusbarSection ;\n" + + " cim:IdentifiedObject.name \"Busbar2\" .\n" + + "\n" + + ":BusbarSection3 rdf:type cim:BusbarSection ;\n" + + " cim:IdentifiedObject.name \"Busbar3\" .\n" + + "\n" + + ":BusbarSection4 rdf:type cim:BusbarSection ;\n" + + " cim:IdentifiedObject.name \"Busbar4\" .\n" + + "\n" + + "# Connectivity Nodes\n" + + ":ConnectivityNode1 a cim:ConnectivityNode .\n" + + ":ConnectivityNode2 a cim:ConnectivityNode .\n" + + ":ConnectivityNode3 a cim:ConnectivityNode .\n" + + ":ConnectivityNode4 a cim:ConnectivityNode .\n" + + ":ConnectivityNode5 a cim:ConnectivityNode .\n" + + ":ConnectivityNode6 a cim:ConnectivityNode .\n" + + "\n" + + "# Terminals connected to ConnectivityNode1 (3 terminals)\n" + + ":Terminal1 cim:Terminal.ConductingEquipment :BusbarSection1 ;\n" + + " cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + + "\n" + + ":Terminal2 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + + ":Terminal3 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" + + "\n" + + "# Terminals connected to ConnectivityNode2 (2 terminals)\n" + + ":Terminal4 cim:Terminal.ConductingEquipment :BusbarSection2 ;\n" + + " cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" + + "\n" + + ":Terminal5 cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" + + "\n" + + "# Terminal connected to ConnectivityNode3 (1 terminal)\n" + + ":Terminal6 cim:Terminal.ConnectivityNode :ConnectivityNode3 .\n" + + "\n" + + "# Terminals connected to ConnectivityNode4 (4 terminals)\n" + + ":Terminal7 cim:Terminal.ConductingEquipment :BusbarSection3 ;\n" + + " cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + + "\n" + + ":Terminal8 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + + ":Terminal9 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + + ":Terminal10 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" + + "\n" + + "# Terminals connected to ConnectivityNode5 (2 terminals)\n" + + ":Terminal11 cim:Terminal.ConductingEquipment :BusbarSection4 ;\n" + + " cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" + + "\n" + + ":Terminal12 cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" + + "\n" + + "# Terminal connected to ConnectivityNode6 (1 terminal)\n" + + ":Terminal13 cim:Terminal.ConnectivityNode :ConnectivityNode6 ."), "", RDFFormat.TURTLE); + } catch (IOException e) { + throw new RuntimeException(e); + } + + try (SailRepositoryConnection connection = sailRepository.getConnection()) { + TupleQuery query = connection.prepareTupleQuery( + "PREFIX rdf: \n" + + "PREFIX cim: \n" + + "" + + "select ?nameSjb1 ?idCN1 ?nbTerm ?idTerm3\n" + + "where {\n" + + " {\n" + + " select ?nameSjb1 ?idCN1 (count(?idTermOfCN) as ?nbTerm)\n" + + " where {\n" + + " ?idSjb1 rdf:type cim:BusbarSection .\n" + + " ?idTerm1 cim:Terminal.ConductingEquipment ?idSjb1 .\n" + + " ?idTerm1 cim:Terminal.ConnectivityNode ?idCN1 .\n" + + " ?idTermOfCN cim:Terminal.ConnectivityNode ?idCN1\n" + + " OPTIONAL { ?idSjb1 cim:IdentifiedObject.name ?nameSjb1 . }\n" + + " }\n" + + " group by ?nameSjb1 ?idCN1\n" + + " having (?nbTerm < 3)\n" + + " }\n" + + " ?idTerm3 cim:Terminal.ConnectivityNode ?idCN1\n" + + "}\n" + + "order by ?nbTerm ?nameSjb1 ?idTerm3"); + String actual = query.explain(Explanation.Level.Executed).toString(); + + assertThat(actual).isEqualToNormalizingNewlines(expected); + + } + sailRepository.shutDown(); + + } + } diff --git a/core/sail/model/pom.xml b/core/sail/model/pom.xml index a4593e109d3..531c473d10a 100644 --- a/core/sail/model/pom.xml +++ b/core/sail/model/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-model RDF4J: Sail Model diff --git a/core/sail/nativerdf/pom.xml b/core/sail/nativerdf/pom.xml index d143946697f..17dbcc1c962 100644 --- a/core/sail/nativerdf/pom.xml +++ b/core/sail/nativerdf/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-nativerdf RDF4J: NativeStore diff --git a/core/sail/pom.xml b/core/sail/pom.xml index 6e5664ecf74..cbce9f38bc7 100644 --- a/core/sail/pom.xml +++ b/core/sail/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail pom diff --git a/core/sail/shacl/pom.xml b/core/sail/shacl/pom.xml index 8028c286e2c..9cae94fe046 100644 --- a/core/sail/shacl/pom.xml +++ b/core/sail/shacl/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-shacl RDF4J: SHACL diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java index f2b75e528ed..81adf25db1d 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSail.java @@ -314,6 +314,8 @@ public static List getSupportedShaclPredicates() { SHACL.TARGET_PROP, SHACL.INVERSE_PATH, SHACL.ALTERNATIVE_PATH, +// SHACL.ONE_OR_MORE_PATH, +// SHACL.ZERO_OR_MORE_PATH, SHACL.NODE, SHACL.QUALIFIED_MAX_COUNT, SHACL.QUALIFIED_MIN_COUNT, diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java index 0688db2316e..dcd9291cba6 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java @@ -202,11 +202,12 @@ public SourceConstraintComponent getConstraintComponent() { @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = constraintComponents.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, Scope.nodeShape, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java index 5735bf9276d..db324f3c020 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java @@ -255,10 +255,11 @@ constraintComponent, getSeverity(), t.getScope(), t.getContexts(), @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = constraintComponents.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, Scope.propertyShape, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/SparqlFragment.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/SparqlFragment.java index e3812aca1a2..c0bc9d2179d 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/SparqlFragment.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/SparqlFragment.java @@ -24,7 +24,6 @@ import org.eclipse.rdf4j.model.Namespace; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; import org.eclipse.rdf4j.sail.shacl.ast.targets.EffectiveTarget; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; @@ -337,8 +336,10 @@ public String getNamespacesForSparql() { return ShaclPrefixParser.toSparqlPrefixes(namespaces); } - public Stream getRoot(ConnectionsGroup connectionsGroup, Resource[] dataGraph, - Path path, StatementMatcher currentStatementMatcher, List currentStatements) { + public Stream getRoot(ConnectionsGroup connectionsGroup, + Resource[] dataGraph, + Path path, StatementMatcher currentStatementMatcher, + List currentStatements) { assert traceBackFunction != null; return traceBackFunction.getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements); } @@ -411,12 +412,12 @@ public int hashCode() { public interface TraceBack { - Stream getRoot( + Stream getRoot( ConnectionsGroup connectionsGroup, Resource[] dataGraph, Path path, StatementMatcher currentStatementMatcher, - List currentStatements); + List currentStatements); } } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/ValidationQuery.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/ValidationQuery.java index f3b6fdd26b6..959b9b04c4b 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/ValidationQuery.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/ValidationQuery.java @@ -232,8 +232,9 @@ private String getFullQueryString() { } else { extraVariablesString = ""; } - } else + } else { extraVariablesString = ""; + } if (scope_validationReport == ConstraintComponent.Scope.propertyShape && propertyShapeWithValue_validationReport) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java index f3a6413a5cb..fedfe846162 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java @@ -103,7 +103,8 @@ public boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { throw new UnsupportedOperationException(); } @@ -171,6 +172,9 @@ static PlanNode getAllTargetsIncludingThoseAddedByPath(ConnectionsGroup connecti null); allTargets = UnionNode.getInstance(connectionsGroup, addedTargets.getPlanNode(), addedByPath); + + allTargets = Unique.getInstance(new TrimToTarget(allTargets, connectionsGroup), false, connectionsGroup); + return allTargets; } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java index 8b7dcde0f50..daba61bd6c0 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java @@ -161,7 +161,8 @@ private PlanNode getAllTargetsBasedOnPredicate(ConnectionsGroup connectionsGroup @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -252,7 +253,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] } - return Unique.getInstance(allTargetsPlan, false, connectionsGroup); + return Unique.getInstance(new TrimToTarget(allTargetsPlan, connectionsGroup), false, connectionsGroup); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java index c9f0c119ba7..9682bc42ee2 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java @@ -28,6 +28,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AllTargetsPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BufferedPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin; @@ -135,7 +136,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections connectionsGroup.getPreviousStateConnection(), b -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); top = UnionNode.getInstance(connectionsGroup, top, bulkedExternalInnerJoin); @@ -218,7 +219,7 @@ private PlanNode getPlanNodeForOverrideTargetNode(ConnectionsGroup connectionsGr Set.of()), false, null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); planNode = connectionsGroup.getCachedNodeFor(planNode); } } @@ -331,7 +332,8 @@ String literalToString(Literal literal) { @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java index aa6bb4f8860..bfc71a8e135 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java @@ -121,10 +121,11 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = and.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java index 8dde6295aff..935c1cf3727 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java @@ -29,6 +29,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AllTargetsPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BufferedSplitter; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin; @@ -171,7 +172,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); if (connectionsGroup.getAddedStatements() != null) { // filter by type against the added statements @@ -236,7 +237,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java index 64bf3dcc2f0..a12cc650c84 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java @@ -39,6 +39,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; import org.eclipse.rdf4j.sail.shacl.ast.paths.SimplePath; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BufferedSplitter; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.ExternalFilterByQuery; @@ -192,7 +193,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); StatementMatcher.Variable subjectVariable = stableRandomVariableProvider.next(); StatementMatcher.Variable predicateVariable = stableRandomVariableProvider.next(); @@ -317,7 +318,10 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections } return validationTuple; }, - connectionsGroup); + connectionsGroup, + List.of(AbstractBulkJoinPlanNode.DEFAULT_VARS.get(0), AbstractBulkJoinPlanNode.DEFAULT_VARS.get(1), + predicateVariable) + ); return bulkedExternalInnerJoin; } @@ -326,7 +330,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { EffectiveTarget effectiveTarget = getTargetChain().getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider); @@ -529,11 +534,6 @@ private String getFilter(StatementMatcher.Variable target, return sparqlFragment.getFragment(); } - @Override - public ValidationApproach getPreferredValidationApproach(ConnectionsGroup connectionsGroup) { - return super.getPreferredValidationApproach(connectionsGroup); - } - @Override public ValidationApproach getOptimalBulkValidationApproach() { return ValidationApproach.SPARQL; diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java index 15a153cfc6c..e051b20057c 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java @@ -63,7 +63,8 @@ boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope, Resou SourceConstraintComponent getConstraintComponent(); PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider); + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings); SparqlFragment buildSparqlValidNodes_rsx_targetShape(Variable subject, Variable object, RdfsSubClassOfReasoner rdfsSubClassOfReasoner, Scope scope, diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java index 450b0ce4ecd..2839d3bcd71 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java @@ -31,6 +31,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher.Variable; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByFilter; @@ -113,7 +114,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider, Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); PlanNode invalidTargets = new GroupByFilter(joined, group -> { return group.stream().map(ValidationTuple::getValue).noneMatch(hasValueIn::contains); @@ -149,7 +150,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java index 7dbfea97a80..a4f3d66b11c 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java @@ -30,6 +30,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByFilter; @@ -98,16 +99,18 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections EffectiveTarget.Extend.left, false, null); addedTargets = UnionNode.getInstance(connectionsGroup, addedByPath, addedTargets); - addedTargets = Unique.getInstance(addedTargets, false, connectionsGroup); } + addedTargets = Unique.getInstance(new TrimToTarget(addedTargets, connectionsGroup), false, + connectionsGroup); + PlanNode joined = new BulkedExternalLeftOuterJoin(addedTargets, connectionsGroup.getBaseConnection(), validationSettings.getDataGraph(), path.getTargetQueryFragment(new Variable<>("a"), new Variable<>("c"), connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider, Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); PlanNode invalidTargets = new GroupByFilter(joined, group -> { return group @@ -144,7 +147,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java index b9564ba2e35..f38c04ac44a 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java @@ -32,6 +32,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode; @@ -113,7 +114,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); } else { relevantTargetsWithPath = new BulkedExternalLeftOuterJoin( mergeNode, @@ -126,7 +127,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); } relevantTargetsWithPath = connectionsGroup.getCachedNodeFor(relevantTargetsWithPath); @@ -140,7 +141,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java index 19ebb4c0787..7f4f4af9ae6 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java @@ -29,6 +29,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByCountFilter; @@ -82,6 +83,10 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections PlanNode addedByPath = getTargetChain().getPath() .get() .getAnyAdded(connectionsGroup, validationSettings.getDataGraph(), null); + + // we don't need to compress here because we are anyway going to trim to target later on + addedByPath = Unique.getInstance(addedByPath, false, connectionsGroup); + LeftOuterJoin leftOuterJoin = new LeftOuterJoin(target, addedByPath, connectionsGroup); target = new GroupByCountFilter(leftOuterJoin, count -> count < minCount, connectionsGroup); } @@ -97,6 +102,10 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections PlanNode addedByPath = getTargetChain().getPath() .get() .getAnyAdded(connectionsGroup, validationSettings.getDataGraph(), null); + + // we don't need to compress here because we are anyway going to trim to target later on + addedByPath = Unique.getInstance(addedByPath, false, connectionsGroup); + LeftOuterJoin leftOuterJoin = new LeftOuterJoin(target, addedByPath, connectionsGroup); target = new GroupByCountFilter(leftOuterJoin, count -> count < minCount, connectionsGroup); } @@ -110,7 +119,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider, Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); relevantTargetsWithPath = connectionsGroup.getCachedNodeFor(relevantTargetsWithPath); @@ -123,7 +132,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return EmptyNode.getInstance(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java index a4d4a208b2d..40f793308ac 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java @@ -101,7 +101,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections planNodeProvider = overrideTargetNode; } else { planNodeProvider = () -> getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = not.generateTransactionalValidationPlan( @@ -166,7 +166,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode allTargets; if (scope == Scope.propertyShape) { @@ -186,7 +187,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] } PlanNode notTargets = not.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + new StatementMatcher.StableRandomVariableProvider(), validationSettings); return Unique.getInstance(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, notTargets), false, connectionsGroup); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java index db9c6744675..393e7cbd9a4 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java @@ -121,7 +121,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections } else { planNodeProvider = BufferedSplitter.getInstance( getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider), + stableRandomVariableProvider, validationSettings), false); } @@ -141,7 +141,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode allTargets; if (scope == Scope.propertyShape) { @@ -162,7 +163,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] PlanNode planNode = or.stream() .map(or -> or.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/PatternConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/PatternConstraintComponent.java index 7e1f164a873..8536421133f 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/PatternConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/PatternConstraintComponent.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.Set; import java.util.function.Function; +import java.util.regex.Pattern; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Literal; @@ -30,11 +31,16 @@ import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PatternFilter; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PatternConstraintComponent extends AbstractSimpleConstraintComponent { + private static final Logger logger = LoggerFactory.getLogger(PatternConstraintComponent.class); + String pattern; String flags; + private final Pattern compiledPattern; public PatternConstraintComponent(String pattern, String flags) { super(); @@ -44,6 +50,52 @@ public PatternConstraintComponent(String pattern, String flags) { if (flags == null) { this.flags = ""; } + + if (flags != null && !flags.isEmpty()) { + int flag = 0b0; + + if (flags.contains("i")) { + flag = flag | Pattern.CASE_INSENSITIVE; + logger.trace("PatternFilter constructed with case insensitive flag"); + } + + if (flags.contains("d")) { + flag = flag | Pattern.UNIX_LINES; + logger.trace("PatternFilter constructed with UNIX lines flag"); + } + + if (flags.contains("m")) { + flag = flag | Pattern.MULTILINE; + logger.trace("PatternFilter constructed with multiline flag"); + } + + if (flags.contains("s")) { + flag = flag | Pattern.DOTALL; + logger.trace("PatternFilter constructed with dotall flag"); + } + + if (flags.contains("u")) { + flag = flag | Pattern.UNICODE_CASE; + logger.trace("PatternFilter constructed with unicode case flag"); + } + + if (flags.contains("x")) { + flag = flag | Pattern.COMMENTS; + logger.trace("PatternFilter constructed with comments flag"); + } + + if (flags.contains("U")) { + flag = flag | Pattern.UNICODE_CHARACTER_CLASS; + logger.trace("PatternFilter constructed with unicode character class flag"); + } + + this.compiledPattern = Pattern.compile(pattern, flag); + logger.trace("PatternFilter constructed with pattern: {} and flags: {}", pattern, flags); + + } else { + this.compiledPattern = Pattern.compile(pattern, 0b0); + logger.trace("PatternFilter constructed with pattern: {} and no flags", pattern); + } } @Override @@ -87,7 +139,7 @@ public ConstraintComponent deepClone() { @Override Function getFilterAttacher(ConnectionsGroup connectionsGroup) { - return (parent) -> new PatternFilter(parent, pattern, flags, connectionsGroup); + return (parent) -> new PatternFilter(parent, compiledPattern, connectionsGroup); } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java index 6394c2f9114..63b660bf6f5 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java @@ -28,11 +28,14 @@ import org.eclipse.rdf4j.sail.shacl.ast.Cache; import org.eclipse.rdf4j.sail.shacl.ast.NodeShape; import org.eclipse.rdf4j.sail.shacl.ast.PropertyShape; +import org.eclipse.rdf4j.sail.shacl.ast.ShaclParsingException; import org.eclipse.rdf4j.sail.shacl.ast.ShaclProperties; import org.eclipse.rdf4j.sail.shacl.ast.ShaclUnsupportedException; import org.eclipse.rdf4j.sail.shacl.ast.Shape; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; +import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByCountFilter; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.LeftOuterJoin; @@ -120,22 +123,27 @@ public ValidationQuery generateSparqlValidationQuery(ConnectionsGroup connection public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connectionsGroup, ValidationSettings validationSettings, PlanNodeProvider overrideTargetNode, Scope scope) { - assert scope == Scope.propertyShape; + + if (scope != Scope.propertyShape) { + throw new ShaclParsingException( + "QualifiedMaxCountConstraintComponent can only be used on property shapes!"); + } StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider = new StatementMatcher.StableRandomVariableProvider(); PlanNode target; + EffectiveTarget effectiveTarget = getTargetChain().getEffectiveTarget(scope, + connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider); + if (overrideTargetNode != null) { - target = getTargetChain() - .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), - stableRandomVariableProvider) + target = effectiveTarget .extend(overrideTargetNode.getPlanNode(), connectionsGroup, validationSettings.getDataGraph(), scope, EffectiveTarget.Extend.right, false, null); } else { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = negated(connectionsGroup, validationSettings, overrideTargetNode, scope); @@ -159,7 +167,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { target = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -182,7 +190,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); return new TupleMapper(relevantTargetsWithPath, t -> { List targetChain = t.getTargetChain(true); @@ -204,7 +212,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { allTargetsPlan = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { allTargetsPlan = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -226,7 +234,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider, Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); invalid = new NotValuesIn(allTargetsPlan, invalid, connectionsGroup); @@ -236,20 +244,29 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { assert scope == Scope.propertyShape; - PlanNode allTargets = getTargetChain() + EffectiveTarget effectiveTarget = getTargetChain() .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(), - stableRandomVariableProvider) - .getPlanNode(connectionsGroup, dataGraph, Scope.propertyShape, true, null); + stableRandomVariableProvider); - PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + Path path = getTargetChain().getPath().orElseThrow(); - return Unique - .getInstance(new TrimToTarget(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), - connectionsGroup), false, connectionsGroup); + PlanNode allTargets = getAllTargetsIncludingThoseAddedByPath(connectionsGroup, validationSettings, scope, + effectiveTarget, path, false); + + PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, + new StatementMatcher.StableRandomVariableProvider(), validationSettings); + + return Unique.getInstance( + new TrimToTarget( + UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), + connectionsGroup + ), + false, connectionsGroup + ); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java index 69c499a0fbc..a3ad8f3a70e 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java @@ -34,6 +34,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.Shape; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AllTargetsPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByCountFilter; @@ -138,7 +139,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null); } else { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = negated(connectionsGroup, validationSettings, overrideTargetNode, scope); @@ -162,7 +163,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { PlanNode planNode = overrideTargetNode.getPlanNode(); if (planNode instanceof AllTargetsPlanNode) { @@ -189,7 +190,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); return new TupleMapper(relevantTargetsWithPath, t -> { List targetChain = t.getTargetChain(true); @@ -210,7 +211,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va PlanNode allTargetsPlan; if (overrideTargetNode == null) { allTargetsPlan = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { allTargetsPlan = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -240,7 +241,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va Set.of()), (b) -> new ValidationTuple(b.getValue("a"), b.getValue("c"), scope, true, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); } invalid = new NotValuesIn(allTargetsPlan, invalid, connectionsGroup); @@ -251,7 +252,8 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { assert scope == Scope.propertyShape; PlanNode allTargets = getTargetChain() @@ -260,7 +262,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] .getPlanNode(connectionsGroup, dataGraph, Scope.propertyShape, true, null); PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + new StatementMatcher.StableRandomVariableProvider(), validationSettings); return Unique .getInstance(new TrimToTarget(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java index 512ae5b338b..77af99c9376 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java @@ -224,7 +224,8 @@ private PlanNode getPlanNodeForOverrideTargetNode(ConnectionsGroup connectionsGr @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider) .getAllTargets(connectionsGroup, dataGraph, scope); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java index 453ff412372..99858731510 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java @@ -27,6 +27,7 @@ import org.eclipse.rdf4j.sail.shacl.ast.ValidationApproach; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalInnerJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.EmptyNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.InnerJoin; @@ -120,7 +121,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider); Optional path = getTargetChain().getPath(); - if (!path.isPresent() || scope != Scope.propertyShape) { + if (path.isEmpty() || scope != Scope.propertyShape) { throw new IllegalStateException("UniqueLang only operates on paths"); } @@ -142,7 +143,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); PlanNode nonUniqueTargetLang = new NonUniqueTargetLang(relevantTargetsWithPath, connectionsGroup); return Unique.getInstance(new TrimToTarget(nonUniqueTargetLang, connectionsGroup), false, connectionsGroup); @@ -189,8 +190,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null, BulkedExternalInnerJoin.getMapper("a", "c", scope, validationSettings.getDataGraph()), - - connectionsGroup); + connectionsGroup, AbstractBulkJoinPlanNode.DEFAULT_VARS); PlanNode nonUniqueTargetLang = new NonUniqueTargetLang(relevantTargetsWithPath, connectionsGroup); @@ -200,7 +200,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java index f2bdcc3d1e6..f658cf12b45 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java @@ -59,7 +59,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return EmptyNode.getInstance(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/AlternativePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/AlternativePath.java index 2d40f5430f0..b57c043de9b 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/AlternativePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/AlternativePath.java @@ -19,7 +19,6 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.vocabulary.SHACL; import org.eclipse.rdf4j.sail.shacl.ast.ShaclAstLists; import org.eclipse.rdf4j.sail.shacl.ast.SparqlFragment; @@ -128,12 +127,12 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, return SparqlFragment.union(sparqlFragments, (ConnectionsGroup connectionsGroup, Resource[] dataGraph, Path path, - StatementMatcher currentStatementMatcher, List currentStatements) -> { - + StatementMatcher currentStatementMatcher, + List currentStatements) -> { return sparqlFragments.stream() .flatMap(sparqlFragment -> sparqlFragment.getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements)) - .filter(EffectiveTarget.StatementsAndMatcher::hasStatements); + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements); } ); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/InversePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/InversePath.java index eb2b3f72be4..4dab52a839b 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/InversePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/InversePath.java @@ -94,7 +94,7 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, Set inheritedVarNames) { return path.getTargetQueryFragment(object, subject, rdfsSubClassOfReasoner, - stableRandomVariableProvider, Set.of()); + stableRandomVariableProvider, inheritedVarNames); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/OneOrMorePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/OneOrMorePath.java index 1427206756b..bab4e2c8e96 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/OneOrMorePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/OneOrMorePath.java @@ -11,21 +11,35 @@ package org.eclipse.rdf4j.sail.shacl.ast.paths; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import java.util.stream.Stream; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.vocabulary.SHACL; -import org.eclipse.rdf4j.sail.shacl.ast.ShaclUnsupportedException; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.shacl.ast.SparqlFragment; +import org.eclipse.rdf4j.sail.shacl.ast.SparqlQueryParserCache; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; +import org.eclipse.rdf4j.sail.shacl.ast.constraintcomponents.ConstraintComponent; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeWrapper; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.SingletonBindingSet; +import org.eclipse.rdf4j.sail.shacl.ast.targets.EffectiveTarget; +import org.eclipse.rdf4j.sail.shacl.ast.targets.TargetChainRetriever; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; import org.eclipse.rdf4j.sail.shacl.wrapper.data.RdfsSubClassOfReasoner; import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource; +import com.google.common.collect.Sets; + public class OneOrMorePath extends Path { private final Path path; @@ -42,7 +56,7 @@ public OneOrMorePath(Resource id, Path path) { @Override public String toString() { - return "ZeroOrOnePath{ " + path + " }"; + return "OneOrMorePath{ " + path + " }"; } @Override @@ -54,7 +68,25 @@ public void toModel(Resource subject, IRI predicate, Model model, Set @Override public PlanNode getAllAdded(ConnectionsGroup connectionsGroup, Resource[] dataGraph, PlanNodeWrapper planNodeWrapper) { - throw new ShaclUnsupportedException(); + var variables = List.of(new StatementMatcher.Variable<>("subject"), + new StatementMatcher.Variable<>("value")); + + SparqlFragment targetQueryFragment = getTargetQueryFragment(variables.get(0), variables.get(1), + connectionsGroup.getRdfsSubClassOfReasoner(), new StatementMatcher.StableRandomVariableProvider(), + Set.of()); + + PlanNode targetChainRetriever = new TargetChainRetriever(connectionsGroup, dataGraph, + targetQueryFragment.getStatementMatchers(), List.of(), null, targetQueryFragment, + variables, + ConstraintComponent.Scope.propertyShape, true); + + targetChainRetriever = connectionsGroup.getCachedNodeFor(targetChainRetriever); + + if (planNodeWrapper != null) { + targetChainRetriever = planNodeWrapper.apply(targetChainRetriever); + } + + return connectionsGroup.getCachedNodeFor(targetChainRetriever); } @Override @@ -81,7 +113,88 @@ public String toSparqlPathString() { public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, StatementMatcher.Variable object, RdfsSubClassOfReasoner rdfsSubClassOfReasoner, StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, Set inheritedVarNames) { - throw new ShaclUnsupportedException(); + + if (inheritedVarNames.isEmpty()) { + inheritedVarNames = Set.of(subject.getName()); + } else { + inheritedVarNames = Sets.union(inheritedVarNames, Set.of(subject.getName())); + } + + String variablePrefix = getVariablePrefix(subject, object); + + String sparqlPathString = path.toSparqlPathString(); + + StatementMatcher.Variable pathStart = new StatementMatcher.Variable(subject, variablePrefix + "start"); + StatementMatcher.Variable pathEnd = new StatementMatcher.Variable(subject, variablePrefix + "end"); + + SparqlFragment targetQueryFragmentMiddle = path.getTargetQueryFragment(pathStart, pathEnd, + rdfsSubClassOfReasoner, stableRandomVariableProvider, + inheritedVarNames); + + SparqlFragment targetQueryFragmentExactlyOne = path.getTargetQueryFragment(subject, object, + rdfsSubClassOfReasoner, stableRandomVariableProvider, + inheritedVarNames); + + String twoOrMore = subject.asSparqlVariable() + " (" + sparqlPathString + ")+ " + pathStart.asSparqlVariable() + + " .\n" + + targetQueryFragmentMiddle.getFragment() + "\n" + + pathEnd.asSparqlVariable() + " (" + sparqlPathString + ")* " + object.asSparqlVariable() + " .\n"; + + SparqlFragment twoOrMoreBgp = SparqlFragment.bgp(List.of(), twoOrMore, + targetQueryFragmentMiddle.getStatementMatchers()); + + var temp = inheritedVarNames; + + return SparqlFragment.union(List.of(targetQueryFragmentExactlyOne, twoOrMoreBgp), + (connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) -> { + + Stream statementsAndMatcherStream1 = targetQueryFragmentExactlyOne + .getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements); + + Stream peek = targetQueryFragmentMiddle + .getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements) + .map(a -> { + SailConnection baseConnection = connectionsGroup.getBaseConnection(); + + String subjectName = a.getStatementMatcher().getSubjectName(); + assert subjectName.equals(pathStart.getName()); + + String query = "select distinct " + subject.asSparqlVariable() + " where {\n" + + subject.asSparqlVariable() + " (" + sparqlPathString + ")+ " + + pathStart.asSparqlVariable() + "\n}"; + + TupleExpr tupleExpr = SparqlQueryParserCache.get(query); + + List statements = new ArrayList<>(); + + for (EffectiveTarget.SubjectObjectAndMatcher.SubjectObject statement : a + .getStatements()) { + try (CloseableIteration evaluate = baseConnection.evaluate( + tupleExpr, PlanNodeHelper.asDefaultGraphDataset(dataGraph), + new SingletonBindingSet(subjectName, statement.getSubject()), true)) { + while (evaluate.hasNext()) { + BindingSet next = evaluate.next(); + statements.add(new EffectiveTarget.SubjectObjectAndMatcher.SubjectObject( + ((Resource) next.getValue(subject.getName())), null)); + } + } + } + + StatementMatcher statementMatcher = new StatementMatcher(subject, null, null, path, + temp); + + EffectiveTarget.SubjectObjectAndMatcher effectiveTarget = new EffectiveTarget.SubjectObjectAndMatcher( + statements, statementMatcher); + + return effectiveTarget; + }); + + return Stream.concat(statementsAndMatcherStream1, peek); + + }); + } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/Path.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/Path.java index 988e8bd7853..7ea5363f276 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/Path.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/Path.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.sail.shacl.ast.paths; +import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -19,6 +20,8 @@ import org.eclipse.rdf4j.model.Namespace; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; import org.eclipse.rdf4j.sail.shacl.ast.Exportable; import org.eclipse.rdf4j.sail.shacl.ast.Identifiable; import org.eclipse.rdf4j.sail.shacl.ast.ShaclUnsupportedException; @@ -28,9 +31,13 @@ import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeWrapper; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class Path implements Identifiable, Exportable, Targetable { + private static final Logger logger = LoggerFactory.getLogger(ShaclSailConnection.class); + Resource id; public Path(Resource id) { @@ -49,31 +56,66 @@ static public Path buildPath(ShapeSource shapeSource, Resource id) { if (id.isBNode()) { List collect = shapeSource.getAllStatements(id) + .filter(statement -> !statement.getPredicate().equals(RDF.TYPE)) .collect(Collectors.toList()); + Path ret = null; + for (Statement statement : collect) { IRI pathType = statement.getPredicate(); switch (pathType.toString()) { case "http://www.w3.org/ns/shacl#inversePath": - return new InversePath(id, (Resource) statement.getObject(), shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new InversePath(id, (Resource) statement.getObject(), shapeSource); + break; case "http://www.w3.org/ns/shacl#alternativePath": - return new AlternativePath(id, (Resource) statement.getObject(), shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new AlternativePath(id, (Resource) statement.getObject(), shapeSource); + break; case "http://www.w3.org/ns/shacl#zeroOrMorePath": - return new ZeroOrMorePath(id, (Resource) statement.getObject(), shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new ZeroOrMorePath(id, (Resource) statement.getObject(), shapeSource); + break; case "http://www.w3.org/ns/shacl#oneOrMorePath": - return new OneOrMorePath(id, (Resource) statement.getObject(), shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new OneOrMorePath(id, (Resource) statement.getObject(), shapeSource); + break; case "http://www.w3.org/ns/shacl#zeroOrOnePath": - return new ZeroOrOnePath(id, (Resource) statement.getObject(), shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new ZeroOrOnePath(id, (Resource) statement.getObject(), shapeSource); + break; case "http://www.w3.org/1999/02/22-rdf-syntax-ns#first": - return new SequencePath(id, shapeSource); + if (ret != null) { + logger.error("Multiple path types not supported! {}", Arrays.toString(collect.toArray())); + } + ret = new SequencePath(id, shapeSource); + break; default: break; } } - throw new ShaclUnsupportedException(); + if (ret != null) { + return ret; + } else { + if (collect.size() == 1) { + throw new ShaclUnsupportedException("Unknown path type: " + collect.get(0)); + } else { + throw new ShaclUnsupportedException("Unknown path type: " + Arrays.toString(collect.toArray())); + } + } } else { return new SimplePath((IRI) id); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SequencePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SequencePath.java index 0580f9a1e7b..ce6baae67fa 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SequencePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SequencePath.java @@ -21,7 +21,6 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.sail.shacl.ast.ShaclAstLists; import org.eclipse.rdf4j.sail.shacl.ast.SparqlFragment; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; @@ -159,8 +158,9 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, return SparqlFragment.join(sparqlFragments, (ConnectionsGroup connectionsGroup, Resource[] dataGraph, Path path, - StatementMatcher currentStatementMatcher, List currentStatements) -> { - Stream currentRoot = null; + StatementMatcher currentStatementMatcher, + List currentStatements) -> { + Stream currentRoot = null; for (int i = sparqlFragments.size() - 1; i >= 0; i--) { SparqlFragment sparqlFragment = sparqlFragments.get(i); @@ -169,7 +169,7 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, .flatMap(root -> sparqlFragment.getRoot(connectionsGroup, dataGraph, path, root.getStatementMatcher(), root.getStatements())) - .filter(EffectiveTarget.StatementsAndMatcher::hasStatements); + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements); } else { currentRoot = sparqlFragment.getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SimplePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SimplePath.java index ce143ab05e0..271c6f50d95 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SimplePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/SimplePath.java @@ -80,16 +80,20 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, StatementMatcher statementMatcher = new StatementMatcher(subject, new StatementMatcher.Variable(predicate), object, this, inheritedVarNames); + return SparqlFragment.bgp(List.of(), subject.asSparqlVariable() + " <" + predicate + "> " + object.asSparqlVariable() + " .", statementMatcher, (connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) -> { if (currentStatementMatcher.getOrigin() == this) { - assert currentStatementMatcher == statementMatcher; + if (currentStatementMatcher != statementMatcher) { + return null; + } return Stream.of( - new EffectiveTarget.StatementsAndMatcher(currentStatements, currentStatementMatcher)); + new EffectiveTarget.SubjectObjectAndMatcher(currentStatements, + currentStatementMatcher)); } else { if (currentStatementMatcher.hasSubject(object)) { - List newStatements = currentStatements.stream() + var newStatements = currentStatements.stream() .map(currentStatement -> { try (CloseableIteration statements = connectionsGroup .getBaseConnection() @@ -99,10 +103,12 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, } }) .flatMap(List::stream) + .map(EffectiveTarget.SubjectObjectAndMatcher.SubjectObject::new) .collect(Collectors.toList()); - return Stream.of(new EffectiveTarget.StatementsAndMatcher(newStatements, statementMatcher)); + return Stream + .of(new EffectiveTarget.SubjectObjectAndMatcher(newStatements, statementMatcher)); } else if (currentStatementMatcher.hasObject(object)) { - List newStatements = currentStatements.stream() + var newStatements = currentStatements.stream() .map(currentStatement -> { try (CloseableIteration statements = connectionsGroup .getBaseConnection() @@ -112,8 +118,10 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, } }) .flatMap(List::stream) + .map(EffectiveTarget.SubjectObjectAndMatcher.SubjectObject::new) .collect(Collectors.toList()); - return Stream.of(new EffectiveTarget.StatementsAndMatcher(newStatements, statementMatcher)); + return Stream + .of(new EffectiveTarget.SubjectObjectAndMatcher(newStatements, statementMatcher)); } return null; diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java index a1f691920eb..f1973fca581 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java @@ -11,21 +11,36 @@ package org.eclipse.rdf4j.sail.shacl.ast.paths; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import java.util.stream.Stream; +import org.apache.commons.lang3.NotImplementedException; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.vocabulary.SHACL; -import org.eclipse.rdf4j.sail.shacl.ast.ShaclUnsupportedException; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.shacl.ast.SparqlFragment; +import org.eclipse.rdf4j.sail.shacl.ast.SparqlQueryParserCache; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; +import org.eclipse.rdf4j.sail.shacl.ast.constraintcomponents.ConstraintComponent; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNode; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeWrapper; +import org.eclipse.rdf4j.sail.shacl.ast.planNodes.SingletonBindingSet; +import org.eclipse.rdf4j.sail.shacl.ast.targets.EffectiveTarget; +import org.eclipse.rdf4j.sail.shacl.ast.targets.TargetChainRetriever; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; import org.eclipse.rdf4j.sail.shacl.wrapper.data.RdfsSubClassOfReasoner; import org.eclipse.rdf4j.sail.shacl.wrapper.shape.ShapeSource; +import com.google.common.collect.Sets; + public class ZeroOrMorePath extends Path { private final Path path; @@ -54,7 +69,25 @@ public void toModel(Resource subject, IRI predicate, Model model, Set @Override public PlanNode getAllAdded(ConnectionsGroup connectionsGroup, Resource[] dataGraph, PlanNodeWrapper planNodeWrapper) { - throw new ShaclUnsupportedException(); + var variables = List.of(new StatementMatcher.Variable<>("subject"), + new StatementMatcher.Variable<>("value")); + + SparqlFragment targetQueryFragment = getTargetQueryFragment(variables.get(0), variables.get(1), + connectionsGroup.getRdfsSubClassOfReasoner(), new StatementMatcher.StableRandomVariableProvider(), + Set.of()); + + PlanNode targetChainRetriever = new TargetChainRetriever(connectionsGroup, dataGraph, + targetQueryFragment.getStatementMatchers(), List.of(), null, targetQueryFragment, + variables, + ConstraintComponent.Scope.propertyShape, true); + + targetChainRetriever = connectionsGroup.getCachedNodeFor(targetChainRetriever); + + if (planNodeWrapper != null) { + targetChainRetriever = planNodeWrapper.apply(targetChainRetriever); + } + + return connectionsGroup.getCachedNodeFor(targetChainRetriever); } @Override @@ -81,7 +114,98 @@ public String toSparqlPathString() { public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, StatementMatcher.Variable object, RdfsSubClassOfReasoner rdfsSubClassOfReasoner, StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, Set inheritedVarNames) { - throw new ShaclUnsupportedException(); + + if (inheritedVarNames.isEmpty()) { + inheritedVarNames = Set.of(subject.getName()); + } else { + inheritedVarNames = Sets.union(inheritedVarNames, Set.of(subject.getName())); + } + + String variablePrefix = getVariablePrefix(subject, object); + + String sparqlPathString = path.toSparqlPathString(); + + StatementMatcher.Variable pathStart = new StatementMatcher.Variable(subject, variablePrefix + "start"); + StatementMatcher.Variable pathEnd = new StatementMatcher.Variable(subject, variablePrefix + "end"); + + SparqlFragment targetQueryFragmentMiddle = path.getTargetQueryFragment(pathStart, pathEnd, + rdfsSubClassOfReasoner, stableRandomVariableProvider, + inheritedVarNames); + + SparqlFragment targetQueryFragmentZeroOrOne = SparqlFragment.bgp(List.of(), + subject.asSparqlVariable() + " (" + sparqlPathString + ")? " + object.asSparqlVariable(), + List.of(new StatementMatcher(subject, null, object, this, inheritedVarNames)), + (connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) -> { + // TODO: We don't have any tests that cover this! Maybe take a look at minCount/oneOrMorePath? + if (currentStatementMatcher.hasSubject(subject)) { + System.out.println(); + throw new NotImplementedException("This should not happen!"); + } + + return Stream.empty(); + } + ); + + String oneOrMore = subject.asSparqlVariable() + " (" + sparqlPathString + ")* " + pathStart.asSparqlVariable() + + " .\n" + + targetQueryFragmentMiddle.getFragment() + "\n" + + pathEnd.asSparqlVariable() + " (" + sparqlPathString + ")* " + object.asSparqlVariable() + " .\n"; + + SparqlFragment oneOrMoreBgp = SparqlFragment.bgp(List.of(), oneOrMore, + targetQueryFragmentMiddle.getStatementMatchers()); + + var temp = inheritedVarNames; + + return SparqlFragment.union(List.of(targetQueryFragmentZeroOrOne, oneOrMoreBgp), + (connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) -> { + + Stream statementsAndMatcherStream1 = targetQueryFragmentZeroOrOne + .getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements); + + Stream peek = targetQueryFragmentMiddle + .getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, currentStatements) + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements) + .map(a -> { + SailConnection baseConnection = connectionsGroup.getBaseConnection(); + + String subjectName = a.getStatementMatcher().getSubjectName(); + assert subjectName.equals(pathStart.getName()); + + String query = "select distinct " + subject.asSparqlVariable() + " where {\n" + + subject.asSparqlVariable() + " (" + sparqlPathString + ")* " + + pathStart.asSparqlVariable() + "\n}"; + + TupleExpr tupleExpr = SparqlQueryParserCache.get(query); + + List statements = new ArrayList<>(); + + for (EffectiveTarget.SubjectObjectAndMatcher.SubjectObject statement : a + .getStatements()) { + try (CloseableIteration evaluate = baseConnection.evaluate( + tupleExpr, PlanNodeHelper.asDefaultGraphDataset(dataGraph), + new SingletonBindingSet(subjectName, statement.getSubject()), true)) { + while (evaluate.hasNext()) { + BindingSet next = evaluate.next(); + statements.add(new EffectiveTarget.SubjectObjectAndMatcher.SubjectObject( + ((Resource) next.getValue(subject.getName())), null)); + } + } + } + + StatementMatcher statementMatcher = new StatementMatcher(subject, null, null, path, + temp); + + EffectiveTarget.SubjectObjectAndMatcher effectiveTarget = new EffectiveTarget.SubjectObjectAndMatcher( + statements, statementMatcher); + + return effectiveTarget; + }); + + return Stream.concat(statementsAndMatcherStream1, peek); + + }); + } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AbstractBulkJoinPlanNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AbstractBulkJoinPlanNode.java index dab0aac9d7e..5ca6b5ca029 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AbstractBulkJoinPlanNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AbstractBulkJoinPlanNode.java @@ -28,18 +28,28 @@ import org.eclipse.rdf4j.query.impl.EmptyBindingSet; import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.shacl.ast.SparqlQueryParserCache; +import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.constraintcomponents.AbstractConstraintComponent; public abstract class AbstractBulkJoinPlanNode implements PlanNode { + public static final List DEFAULT_VARS = List.of(new StatementMatcher.Variable("a"), + new StatementMatcher.Variable("c")); public static final String BINDING_NAME = "a"; protected static final int BULK_SIZE = 1000; - private StackTraceElement[] stackTrace; + private final List vars; + private final String varsQueryString; + StackTraceElement[] stackTrace; protected Function mapper; ValidationExecutionLogger validationExecutionLogger; - public AbstractBulkJoinPlanNode() { -// this.stackTrace = Thread.currentThread().getStackTrace(); + public AbstractBulkJoinPlanNode(List vars) { + this.vars = vars; + this.varsQueryString = vars.stream() + .map(StatementMatcher.Variable::asSparqlVariable) + .reduce((a, b) -> a + " " + b) + .orElseThrow(); + this.stackTrace = Thread.currentThread().getStackTrace(); } TupleExpr parseQuery(String query) { @@ -47,7 +57,8 @@ TupleExpr parseQuery(String query) { // #VALUES_INJECTION_POINT# is an annotation in the query where there is a "new scope" due to the bottom up // semantics of SPARQL but where we don't actually want a new scope. query = query.replace(AbstractConstraintComponent.VALUES_INJECTION_POINT, "\nVALUES (?a) {}\n"); - String completeQuery = "select * where {\nVALUES (?a) {}\n" + query + "\n}"; + + String completeQuery = "select distinct " + varsQueryString + " where {\nVALUES (?a) {}\n" + query + "\n}"; return SparqlQueryParserCache.get(completeQuery); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AllTargetsPlanNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AllTargetsPlanNode.java index 7aacec352ac..4067c60f46b 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AllTargetsPlanNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/AllTargetsPlanNode.java @@ -71,8 +71,9 @@ protected void init() { @Override public void localClose() { - if (iterator != null) + if (iterator != null) { iterator.close(); + } } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalInnerJoin.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalInnerJoin.java index 4fa535418b1..6ea7f9d5e2f 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalInnerJoin.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalInnerJoin.java @@ -61,8 +61,9 @@ public class BulkedExternalInnerJoin extends AbstractBulkJoinPlanNode { public BulkedExternalInnerJoin(PlanNode leftNode, SailConnection connection, Resource[] dataGraph, SparqlFragment query, boolean skipBasedOnPreviousConnection, SailConnection previousStateConnection, - Function mapper, ConnectionsGroup connectionsGroup) { - super(); + Function mapper, ConnectionsGroup connectionsGroup, + List vars) { + super(vars); assert !skipBasedOnPreviousConnection || previousStateConnection != null; this.leftNode = PlanNodeHelper.handleSorting(this, leftNode, connectionsGroup); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalLeftOuterJoin.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalLeftOuterJoin.java index ef5689508df..14a94fe20b9 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalLeftOuterJoin.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/BulkedExternalLeftOuterJoin.java @@ -46,8 +46,9 @@ public class BulkedExternalLeftOuterJoin extends AbstractBulkJoinPlanNode { public BulkedExternalLeftOuterJoin(PlanNode leftNode, SailConnection connection, Resource[] dataGraph, SparqlFragment query, - Function mapper, ConnectionsGroup connectionsGroup) { - super(); + Function mapper, ConnectionsGroup connectionsGroup, + List vars) { + super(vars); leftNode = PlanNodeHelper.handleSorting(this, leftNode, connectionsGroup); this.leftNode = leftNode; this.query = query.getNamespacesForSparql() diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DatatypeFilter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DatatypeFilter.java index deeb33dfe2d..16221da1550 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DatatypeFilter.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DatatypeFilter.java @@ -36,7 +36,6 @@ public DatatypeFilter(PlanNode parent, IRI datatype, ConnectionsGroup connection super(parent, connectionsGroup); this.datatype = datatype; this.xsdDatatype = CoreDatatype.from(datatype).asXSDDatatype().orElse(null); -// stackTrace = Thread.currentThread().getStackTrace(); } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DebugPlanNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DebugPlanNode.java index b64d75baa97..0dd48ca7e99 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DebugPlanNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/DebugPlanNode.java @@ -37,7 +37,7 @@ public DebugPlanNode(PlanNode parent, String message, Consumer public DebugPlanNode(PlanNode parent, String message) { this.parent = parent; this.message = message; - // this.stackTrace = Thread.currentThread().getStackTrace(); + this.stackTrace = Thread.currentThread().getStackTrace(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/EqualsJoinValue.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/EqualsJoinValue.java index a8ee407df5a..593e22d9d6b 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/EqualsJoinValue.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/EqualsJoinValue.java @@ -15,8 +15,13 @@ import org.apache.commons.text.StringEscapeUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EqualsJoinValue implements PlanNode { + + static private final Logger logger = LoggerFactory.getLogger(EqualsJoinValue.class); + private final PlanNode left; private final PlanNode right; private final boolean useAsFilter; @@ -29,8 +34,9 @@ public EqualsJoinValue(PlanNode left, PlanNode right, boolean useAsFilter, Conne this.right = PlanNodeHelper.handleSorting(this, right, connectionsGroup); this.useAsFilter = useAsFilter; -// this.stackTrace = Thread.currentThread().getStackTrace(); - + if (logger.isDebugEnabled()) { + this.stackTrace = Thread.currentThread().getStackTrace(); + } } @Override @@ -165,7 +171,9 @@ public String getId() { @Override public String toString() { - return "EqualsJoin{" + "useAsFilter=" + useAsFilter + '}'; + return "EqualsJoinValue{" + + "useAsFilter=" + useAsFilter + + '}'; } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicate.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicate.java index 8c5b49b0218..279664cdace 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicate.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicate.java @@ -21,7 +21,6 @@ import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.memory.MemoryStoreConnection; @@ -36,6 +35,7 @@ public class FilterByPredicate implements PlanNode { private final Set filterOnPredicates; final PlanNode parent; private final On on; + private final ConnectionsGroup connectionsGroup; private boolean printed = false; private ValidationExecutionLogger validationExecutionLogger; private final Resource[] dataGraph; @@ -53,6 +53,7 @@ public FilterByPredicate(SailConnection connection, Set filterOnPredicates, assert this.connection != null; this.filterOnPredicates = filterOnPredicates; this.on = on; + this.connectionsGroup = connectionsGroup; } @Override @@ -77,18 +78,11 @@ void calculateNext() { return; } - filterOnPredicates = FilterByPredicate.this.filterOnPredicates.stream() - .map(predicate -> { - try (var stream = connection - .getStatements(null, predicate, null, true, dataGraph) - .stream()) { - return stream.map(Statement::getPredicate) - .findAny() - .orElse(null); - } - } - ) - .filter(Objects::nonNull) + filterOnPredicates = FilterByPredicate.this.filterOnPredicates + .stream() + .map(iri -> connectionsGroup.getSailSpecificValue(iri, + ConnectionsGroup.StatementPosition.predicate, connection + )) .collect(Collectors.toList()); } @@ -188,8 +182,8 @@ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) { @Override public String toString() { - return "ExternalFilterByPredicate{" + "filterOnPredicates=" - + Arrays.toString(filterOnPredicates.stream().map(Formatter::prefix).toArray()) + return "FilterByPredicate{" + "filterOnPredicates=" + + Formatter.prefix(filterOnPredicates) + '}'; } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicateObject.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicateObject.java index 9a44baba198..cd9dc265ca4 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicateObject.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterByPredicateObject.java @@ -20,12 +20,14 @@ import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.model.Value; +import org.eclipse.rdf4j.model.vocabulary.RDF; import org.eclipse.rdf4j.sail.SailConnection; import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.memory.MemoryStoreConnection; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -35,6 +37,8 @@ */ public class FilterByPredicateObject implements PlanNode { + static private final Logger logger = LoggerFactory.getLogger(FilterByPredicateObject.class); + private final SailConnection connection; private final boolean includeInferred; private final Set filterOnObject; @@ -42,16 +46,19 @@ public class FilterByPredicateObject implements PlanNode { private final FilterOn filterOn; private final PlanNode parent; private final boolean returnMatching; + private final ConnectionsGroup connectionsGroup; private StackTraceElement[] stackTrace; private boolean printed = false; private ValidationExecutionLogger validationExecutionLogger; private final Resource[] dataGraph; + boolean typeFilterWithInference; private final Cache cache; public FilterByPredicateObject(SailConnection connection, Resource[] dataGraph, IRI filterOnPredicate, Set filterOnObject, PlanNode parent, boolean returnMatching, FilterOn filterOn, boolean includeInferred, ConnectionsGroup connectionsGroup) { + this.dataGraph = dataGraph; this.parent = PlanNodeHelper.handleSorting(this, parent, connectionsGroup); this.connection = connection; @@ -68,7 +75,14 @@ public FilterByPredicateObject(SailConnection connection, Resource[] dataGraph, cache = CacheBuilder.newBuilder().maximumSize(10000).build(); } -// this.stackTrace = Thread.currentThread().getStackTrace(); + this.connectionsGroup = connectionsGroup; + if (includeInferred && connectionsGroup.getRdfsSubClassOfReasoner() != null + && RDF.TYPE.equals(filterOnPredicate)) { + typeFilterWithInference = true; + } + if (logger.isDebugEnabled()) { + this.stackTrace = Thread.currentThread().getStackTrace(); + } } @Override @@ -148,31 +162,32 @@ void calculateNext() { private void internResources() { if (filterOnObject == null) { - - try (var stream = connection - .getStatements(null, FilterByPredicateObject.this.filterOnPredicate, null, includeInferred, - dataGraph) - .stream()) { - filterOnPredicate = stream.map(Statement::getPredicate).findAny().orElse(null); - } - + filterOnPredicate = connectionsGroup.getSailSpecificValue( + FilterByPredicateObject.this.filterOnPredicate, + ConnectionsGroup.StatementPosition.predicate, connection + ); if (filterOnPredicate == null) { filterOnObject = new Resource[0]; } else { - filterOnObject = FilterByPredicateObject.this.filterOnObject.stream() - .map(object -> { - try (var stream = connection - .getStatements(null, filterOnPredicate, object, includeInferred, dataGraph) - .stream()) { - return stream.map(Statement::getObject) - .map(o -> ((Resource) o)) - .findAny() - .orElse(null); - } - } - ) - .filter(Objects::nonNull) - .toArray(Resource[]::new); + if (typeFilterWithInference) { + filterOnObject = FilterByPredicateObject.this.filterOnObject.stream() + .flatMap(type -> connectionsGroup.getRdfsSubClassOfReasoner() + .backwardsChain(type) + .stream()) + .distinct() + .map(object -> connectionsGroup.getSailSpecificValue(object, + ConnectionsGroup.StatementPosition.object, connection + )) + .filter(Objects::nonNull) + .toArray(Resource[]::new); + } else { + filterOnObject = FilterByPredicateObject.this.filterOnObject.stream() + .map(object -> connectionsGroup.getSailSpecificValue(object, + ConnectionsGroup.StatementPosition.object, connection + )) + .filter(Objects::nonNull) + .toArray(Resource[]::new); + } } } @@ -237,8 +252,8 @@ private Boolean matchesCached(Resource subject, IRI filterOnPredicate, Resource[ private boolean matchesUnCached(Resource subject, IRI filterOnPredicate, Resource[] filterOnObject) { for (Resource object : filterOnObject) { - if (connection.hasStatement(subject, filterOnPredicate, object, includeInferred, - dataGraph)) { + if (connection.hasStatement(subject, filterOnPredicate, object, + includeInferred && !typeFilterWithInference, dataGraph)) { return true; } } @@ -341,9 +356,9 @@ public int hashCode() { @Override public String toString() { - return "ExternalPredicateObjectFilter{" + "filterOnObject=" + PlanNode.prefix(filterOnObject) + return "FilterByPredicateObject{" + "filterOnObject=" + Formatter.prefix(filterOnObject) + ", filterOnPredicate=" - + PlanNode.prefix(filterOnPredicate) + ", filterOn=" + filterOn + ", returnMatching=" + + Formatter.prefix(filterOnPredicate) + ", filterOn=" + filterOn + ", returnMatching=" + returnMatching + '}'; } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterPlanNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterPlanNode.java index a1879503fc4..c44f511f612 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterPlanNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterPlanNode.java @@ -35,11 +35,13 @@ public abstract class FilterPlanNode implements MultiStreamPlanNode, PlanNode { private CloseableIteration iterator; private ValidationExecutionLogger validationExecutionLogger; private boolean closed; + StackTraceElement[] stackTrace; abstract boolean checkTuple(Reference t); public FilterPlanNode(PlanNode parent, ConnectionsGroup connectionsGroup) { this.parent = PlanNodeHelper.handleSorting(this, parent, connectionsGroup); +// this.stackTrace = Thread.currentThread().getStackTrace(); } public PlanNode getTrueNode(Class type) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsObject.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsObject.java index bdf07046958..bdb80fb8779 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsObject.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsObject.java @@ -42,11 +42,6 @@ boolean checkTuple(Reference t) { return connection.hasStatement(null, null, target, true, dataGraph); } - @Override - public String toString() { - return "ExternalFilterTargetIsObject{" + '}'; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsSubject.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsSubject.java index 02acb30e90f..3124e6f076e 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsSubject.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/FilterTargetIsSubject.java @@ -49,11 +49,6 @@ boolean checkTuple(Reference t) { } - @Override - public String toString() { - return "ExternalFilterTargetIsSubject{}"; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Formatter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Formatter.java index e6f182190ea..62b5cdbc5d2 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Formatter.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Formatter.java @@ -10,20 +10,76 @@ *******************************************************************************/ package org.eclipse.rdf4j.sail.shacl.ast.planNodes; +import java.util.Arrays; import java.util.List; +import java.util.Set; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Namespace; import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.vocabulary.AFN; +import org.eclipse.rdf4j.model.vocabulary.APF; +import org.eclipse.rdf4j.model.vocabulary.CONFIG; +import org.eclipse.rdf4j.model.vocabulary.DASH; +import org.eclipse.rdf4j.model.vocabulary.DC; import org.eclipse.rdf4j.model.vocabulary.DCAT; +import org.eclipse.rdf4j.model.vocabulary.DCTERMS; +import org.eclipse.rdf4j.model.vocabulary.DOAP; +import org.eclipse.rdf4j.model.vocabulary.EARL; +import org.eclipse.rdf4j.model.vocabulary.FN; import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.model.vocabulary.GEO; +import org.eclipse.rdf4j.model.vocabulary.GEOF; +import org.eclipse.rdf4j.model.vocabulary.HYDRA; +import org.eclipse.rdf4j.model.vocabulary.LDP; +import org.eclipse.rdf4j.model.vocabulary.LIST; +import org.eclipse.rdf4j.model.vocabulary.LOCN; +import org.eclipse.rdf4j.model.vocabulary.ODRL2; +import org.eclipse.rdf4j.model.vocabulary.ORG; +import org.eclipse.rdf4j.model.vocabulary.OWL; +import org.eclipse.rdf4j.model.vocabulary.PROV; import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDF4J; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.ROV; +import org.eclipse.rdf4j.model.vocabulary.RSX; +import org.eclipse.rdf4j.model.vocabulary.SD; +import org.eclipse.rdf4j.model.vocabulary.SESAME; +import org.eclipse.rdf4j.model.vocabulary.SESAMEQNAME; import org.eclipse.rdf4j.model.vocabulary.SHACL; +import org.eclipse.rdf4j.model.vocabulary.SKOS; +import org.eclipse.rdf4j.model.vocabulary.SKOSXL; +import org.eclipse.rdf4j.model.vocabulary.SP; +import org.eclipse.rdf4j.model.vocabulary.SPIF; +import org.eclipse.rdf4j.model.vocabulary.SPIN; +import org.eclipse.rdf4j.model.vocabulary.SPINX; +import org.eclipse.rdf4j.model.vocabulary.SPL; +import org.eclipse.rdf4j.model.vocabulary.TIME; +import org.eclipse.rdf4j.model.vocabulary.VANN; +import org.eclipse.rdf4j.model.vocabulary.VCARD4; +import org.eclipse.rdf4j.model.vocabulary.VOID; +import org.eclipse.rdf4j.model.vocabulary.WGS84; import org.eclipse.rdf4j.model.vocabulary.XSD; public class Formatter { + public static String prefix(Set set) { + if (set.size() == 1) { + return prefix(set.iterator().next()); + } + + return Arrays.toString(set.stream().map(Formatter::prefix).toArray()); + } + + public static String prefix(List list) { + if (list.size() == 1) { + return prefix(list.iterator().next()); + } + + return Arrays.toString(list.stream().map(Formatter::prefix).toArray()); + } + public static String prefix(Value in) { if (in == null) { @@ -35,12 +91,51 @@ public static String prefix(Value in) { String namespace = ((IRI) in).getNamespace(); List namespaces = List.of( + AFN.NS, + APF.NS, + CONFIG.NS, + DASH.NS, + DC.NS, + DCAT.NS, + DCTERMS.NS, + DOAP.NS, + EARL.NS, + FN.NS, + FOAF.NS, + GEO.NS, + GEOF.NS, + HYDRA.NS, + LDP.NS, + LIST.NS, + LOCN.NS, + ODRL2.NS, + ORG.NS, + OWL.NS, + PROV.NS, RDF.NS, + RDF4J.NS, + RDFS.NS, + ROV.NS, + RSX.NS, + SD.NS, + SESAME.NS, + SESAMEQNAME.NS, SHACL.NS, - FOAF.NS, - DCAT.NS, + SKOS.NS, + SKOSXL.NS, + SP.NS, + SPIF.NS, + SPIN.NS, + SPINX.NS, + SPL.NS, + TIME.NS, + VANN.NS, + VCARD4.NS, + VOID.NS, + WGS84.NS, + XSD.NS, new SimpleNamespace("http://example.com/ns#", "ex"), - XSD.NS + new SimpleNamespace("http://example.com/ns/", "ex") ); for (Namespace ns : namespaces) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/GroupByFilter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/GroupByFilter.java index 765faab3ba0..038e561f4d0 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/GroupByFilter.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/GroupByFilter.java @@ -135,7 +135,7 @@ public void getPlanAsGraphvizDot(StringBuilder stringBuilder) { @Override public String toString() { - return "GroupByCountFilter"; + return "GroupByFilter"; } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/InnerJoin.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/InnerJoin.java index d6265e37251..517ebd9468e 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/InnerJoin.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/InnerJoin.java @@ -300,7 +300,7 @@ public String getId() { @Override public String toString() { - return "InnerJoin(" + left.toString() + " : " + right.toString() + ")"; + return "InnerJoin"; } private String leadingSpace() { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LeftOuterJoin.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LeftOuterJoin.java index bfe8c47d520..9384889e0d0 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LeftOuterJoin.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LeftOuterJoin.java @@ -119,11 +119,13 @@ void calculateNext() { @Override public void localClose() { try { - if (leftIterator != null) + if (leftIterator != null) { leftIterator.close(); + } } finally { - if (rightIterator != null) + if (rightIterator != null) { rightIterator.close(); + } } } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/NonUniqueTargetLang.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/NonUniqueTargetLang.java index 6ebeb1716ce..83a4424c156 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/NonUniqueTargetLang.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/NonUniqueTargetLang.java @@ -149,7 +149,7 @@ private void calculateNext() { if (value.isLiteral()) { Optional lang = ((Literal) value).getLanguage(); - if (!lang.isPresent()) { + if (lang.isEmpty()) { next = null; } else if (!seenLanguages.contains(lang.get())) { seenLanguages.add(lang.get()); @@ -166,8 +166,9 @@ private void calculateNext() { @Override public void localClose() { - if (parentIterator != null) + if (parentIterator != null) { parentIterator.close(); + } } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PatternFilter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PatternFilter.java index c972ae0e3a0..404cd983da5 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PatternFilter.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PatternFilter.java @@ -34,53 +34,9 @@ public class PatternFilter extends FilterPlanNode { private final Pattern pattern; - public PatternFilter(PlanNode parent, String pattern, String flags, ConnectionsGroup connectionsGroup) { + public PatternFilter(PlanNode parent, Pattern pattern, ConnectionsGroup connectionsGroup) { super(parent, connectionsGroup); - if (flags != null && !flags.isEmpty()) { - int flag = 0b0; - - if (flags.contains("i")) { - flag = flag | Pattern.CASE_INSENSITIVE; - logger.trace("PatternFilter constructed with case insensitive flag"); - } - - if (flags.contains("d")) { - flag = flag | Pattern.UNIX_LINES; - logger.trace("PatternFilter constructed with UNIX lines flag"); - } - - if (flags.contains("m")) { - flag = flag | Pattern.MULTILINE; - logger.trace("PatternFilter constructed with multiline flag"); - } - - if (flags.contains("s")) { - flag = flag | Pattern.DOTALL; - logger.trace("PatternFilter constructed with dotall flag"); - } - - if (flags.contains("u")) { - flag = flag | Pattern.UNICODE_CASE; - logger.trace("PatternFilter constructed with unicode case flag"); - } - - if (flags.contains("x")) { - flag = flag | Pattern.COMMENTS; - logger.trace("PatternFilter constructed with comments flag"); - } - - if (flags.contains("U")) { - flag = flag | Pattern.UNICODE_CHARACTER_CLASS; - logger.trace("PatternFilter constructed with unicode character class flag"); - } - - this.pattern = Pattern.compile(pattern, flag); - logger.trace("PatternFilter constructed with pattern: {} and flags: {}", pattern, flags); - - } else { - this.pattern = Pattern.compile(pattern, 0b0); - logger.trace("PatternFilter constructed with pattern: {} and no flags", pattern); - } + this.pattern = pattern; } private static Literal str(Value argValue, ValueFactory valueFactory) { @@ -104,8 +60,9 @@ boolean checkTuple(Reference t) { Value literal = t.get().getValue(); literal = str(literal, SimpleValueFactory.getInstance()); - if (literal == null) + if (literal == null) { return false; + } if (QueryEvaluationUtility.isStringLiteral(literal)) { boolean result = pattern.matcher(((Literal) literal).getLabel()).find(); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PlanNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PlanNode.java index 919d39323f0..82adf62ac8e 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PlanNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/PlanNode.java @@ -11,9 +11,6 @@ package org.eclipse.rdf4j.sail.shacl.ast.planNodes; -import java.util.Arrays; -import java.util.Set; - import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Value; @@ -23,18 +20,6 @@ */ public interface PlanNode { - static String prefix(Set filterOnObject) { - if (filterOnObject.size() == 1) { - return prefix(filterOnObject.iterator().next()); - } - - return Arrays.toString(filterOnObject.stream().map(PlanNode::prefix).toArray()); - } - - static String prefix(Value value) { - return Formatter.prefix(value); - } - CloseableIteration iterator(); int depth(); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/SetFilterNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/SetFilterNode.java index ad64b910bac..c6564b4b0ab 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/SetFilterNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/SetFilterNode.java @@ -11,7 +11,6 @@ package org.eclipse.rdf4j.sail.shacl.ast.planNodes; -import java.util.Arrays; import java.util.Objects; import java.util.Set; @@ -113,7 +112,7 @@ public String getId() { @Override public String toString() { return "SetFilterNode{" + "targetNodeList=" - + Arrays.toString(targetNodeList.stream().map(Formatter::prefix).toArray()) + ", index=" + index + + Formatter.prefix(targetNodeList) + ", index=" + index + ", returnValid=" + returnValid + '}'; } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToNodeShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToNodeShape.java index e78962815f4..5f1752dbc4a 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToNodeShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToNodeShape.java @@ -19,11 +19,14 @@ import org.apache.commons.text.StringEscapeUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Håvard Ottestad */ public class ShiftToNodeShape implements PlanNode { + static private final Logger logger = LoggerFactory.getLogger(ShiftToNodeShape.class); private StackTraceElement[] stackTrace; PlanNode parent; diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToPropertyShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToPropertyShape.java index 0e501473858..c9d88521e75 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToPropertyShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ShiftToPropertyShape.java @@ -19,11 +19,14 @@ import org.apache.commons.text.StringEscapeUtils; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.sail.shacl.wrapper.data.ConnectionsGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Håvard Ottestad */ public class ShiftToPropertyShape implements PlanNode { + static private final Logger logger = LoggerFactory.getLogger(ShiftToPropertyShape.class); private StackTraceElement[] stackTrace; PlanNode parent; diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/TupleMapper.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/TupleMapper.java index f9f3e0bfb92..127093c4a39 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/TupleMapper.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/TupleMapper.java @@ -85,7 +85,7 @@ public String getId() { @Override public String toString() { - return "ModifyValidationTuple"; + return "TupleMapper"; } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Unique.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Unique.java index 1a0eb2d73b1..d412a74b1a8 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Unique.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/Unique.java @@ -112,6 +112,8 @@ private void calculateNext() { Set tuples = new HashSet<>(); if (propertyShapeWithValue) { + if (parentIterator.hasNext()) + parentIterator.peek(); while (parentIterator.hasNext() && parentIterator.peek().getValue().equals(temp.getValue()) diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValueInFilter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValueInFilter.java index dff0a687f15..dd134c695b9 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValueInFilter.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValueInFilter.java @@ -11,7 +11,6 @@ package org.eclipse.rdf4j.sail.shacl.ast.planNodes; -import java.util.Arrays; import java.util.Objects; import java.util.Set; @@ -37,8 +36,7 @@ boolean checkTuple(Reference t) { @Override public String toString() { - return "ValueInFilter{" + "valueSet=" + Arrays.toString(valueSet.stream().map(Formatter::prefix).toArray()) - + '}'; + return "ValueInFilter{" + "valueSet=" + Formatter.prefix(valueSet) + '}'; } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValuesBackedNode.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValuesBackedNode.java index 3a92d9c2a04..14fb12af7c8 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValuesBackedNode.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/ValuesBackedNode.java @@ -97,7 +97,7 @@ public String getId() { @Override public String toString() { - return "ValuesBackedNode{" + "values=" + values + '}'; + return "ValuesBackedNode{" + "values=" + Formatter.prefix(values) + '}'; } @Override diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-after.txt b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-after.txt deleted file mode 100644 index c089cefe02e..00000000000 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-after.txt +++ /dev/null @@ -1,896 +0,0 @@ -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:129) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-before.txt b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-before.txt deleted file mode 100644 index 6ae9ee9f5c3..00000000000 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/sort-before.txt +++ /dev/null @@ -1,896 +0,0 @@ -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.targets.TargetClass.getTargetFilter(TargetClass.java:128) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) -org.eclipse.rdf4j.sail.shacl.ast.planNodes.PlanNodeHelper.handleSorting(PlanNodeHelper.java:37) diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/EffectiveTarget.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/EffectiveTarget.java index eeadb293dc2..2a9ef7040e1 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/EffectiveTarget.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/EffectiveTarget.java @@ -465,10 +465,13 @@ public EffectiveTargetFragment(Variable var, Targetable target, Effective rootStatementMatcher = null; } else { rootStatementMatcher = queryFragment.getStatementMatchers().get(0); - assert rootStatementMatcher.getSubjectName() == var.getName() || - rootStatementMatcher.getObjectName() == var.getName() || - rootStatementMatcher.getSubjectName() == prev.var.getName() || - rootStatementMatcher.getObjectName() == prev.var.getName(); + if (rootStatementMatcher.getSubjectName() != var.getName() && + rootStatementMatcher.getObjectName() != var.getName() && + rootStatementMatcher.getSubjectName() != prev.var.getName() && + rootStatementMatcher.getObjectName() != prev.var.getName()) { + throw new AssertionError("rootStatementMatcher: " + rootStatementMatcher + ", var: " + var + + ", prev.var: " + prev.var); + } } } @@ -476,7 +479,7 @@ public SparqlFragment getQueryFragment() { return queryFragment; } - public Stream getRoot(ConnectionsGroup connectionsGroup, Resource[] dataGraph, + public Stream getRoot(ConnectionsGroup connectionsGroup, Resource[] dataGraph, StatementMatcher currentStatementMatcher, Statement currentStatement) { if (currentStatementMatcher == rootStatementMatcher) { @@ -507,7 +510,7 @@ public Stream getRoot(ConnectionsGroup connectionsGroup, R assert !(path instanceof InversePath); return queryFragment.getRoot(connectionsGroup, dataGraph, path, currentStatementMatcher, - List.of(currentStatement)); + List.of(new EffectiveTarget.SubjectObjectAndMatcher.SubjectObject(currentStatement))); } throw new UnsupportedOperationException(); @@ -515,20 +518,20 @@ public Stream getRoot(ConnectionsGroup connectionsGroup, R } } - public static class StatementsAndMatcher { - private final List statements; + public static class SubjectObjectAndMatcher { + private final List statements; private final StatementMatcher statementMatcher; // We should support some sort of stream instead, so that we can scale without keeping all the // intermediary statements in memeory! It's very hard to implement though since the list of statements is // iterated over several times in different branches, so we can't just pass in an iterator since it would be // consumed by one branch and then the other branch would only see an empty iterator. - public StatementsAndMatcher(List statements, StatementMatcher statementMatcher) { + public SubjectObjectAndMatcher(List statements, StatementMatcher statementMatcher) { this.statements = statements; this.statementMatcher = statementMatcher; } - public List getStatements() { + public List getStatements() { return statements; } @@ -540,6 +543,29 @@ public boolean hasStatements() { return !statements.isEmpty(); } + public static class SubjectObject { + private final Resource subject; + private final Value object; + + public SubjectObject(Resource subject, Value object) { + this.subject = subject; + this.object = object; + } + + public SubjectObject(Statement statement) { + this.subject = statement.getSubject(); + this.object = statement.getObject(); + } + + public Resource getSubject() { + return subject; + } + + public Value getObject() { + return object; + } + } + @Override public String toString() { return "StatementsAndMatcher{" + diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/TargetChainRetriever.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/TargetChainRetriever.java index 767b7a7a377..5d44319bee3 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/TargetChainRetriever.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/targets/TargetChainRetriever.java @@ -81,6 +81,7 @@ public class TargetChainRetriever implements PlanNode { private final EffectiveTarget.EffectiveTargetFragment removedStatementTarget; private final boolean hasValue; private final Set varNamesInQueryFragment; + private final String queryStr; private final Set originalStatementMatchers; private StackTraceElement[] stackTrace; @@ -122,9 +123,11 @@ public TargetChainRetriever(ConnectionsGroup connectionsGroup, .get(QueryLanguage.SPARQL) .get(); + this.queryStr = "select * where {\n" + this.queryFragment + "\n}"; + this.varNamesInQueryFragment = Set.of(ArrayBindingBasedQueryEvaluationContext .findAllVariablesUsedInQuery(((QueryRoot) queryParserFactory.getParser() - .parseQuery("select * where {\n" + this.queryFragment + "\n}", null) + .parseQuery(queryStr, null) .getTupleExpr()))); assert !varNamesInQueryFragment.isEmpty(); @@ -312,12 +315,14 @@ private List readStatementsInBulk(Set variableNames) { while (bulk.size() < BULK_SIZE && statements.hasNext()) { Statement next = statements.next(); - Stream rootStatements = Stream - .of(new EffectiveTarget.StatementsAndMatcher(List.of(next), currentStatementMatcher)); + Stream rootStatements = Stream + .of(new EffectiveTarget.SubjectObjectAndMatcher( + List.of(new EffectiveTarget.SubjectObjectAndMatcher.SubjectObject(next)), + currentStatementMatcher)); if (chaseRoot()) { // we only need to find the root if the currentStatementMatcher doesn't match anything in the // query - Stream root = removedStatementTarget.getRoot( + Stream root = removedStatementTarget.getRoot( connectionsGroup, dataGraph, currentStatementMatcher, next); @@ -328,7 +333,7 @@ private List readStatementsInBulk(Set variableNames) { } rootStatements - .filter(EffectiveTarget.StatementsAndMatcher::hasStatements) + .filter(EffectiveTarget.SubjectObjectAndMatcher::hasStatements) .flatMap(statementsAndMatcher -> { StatementMatcher newCurrentStatementMatcher = statementsAndMatcher .getStatementMatcher(); @@ -339,6 +344,10 @@ private List readStatementsInBulk(Set variableNames) { Binding[] bindings = new Binding[variableNames.size()]; int j = 0; + assert newCurrentStatementMatcher.getPredicateValue() != null + || !currentVarNames + .contains(newCurrentStatementMatcher.getPredicateName()); + if (newCurrentStatementMatcher.getSubjectValue() == null && currentVarNames .contains(newCurrentStatementMatcher.getSubjectName())) { @@ -347,14 +356,6 @@ private List readStatementsInBulk(Set variableNames) { temp.getSubject()); } - if (newCurrentStatementMatcher.getPredicateValue() == null - && currentVarNames - .contains(newCurrentStatementMatcher.getPredicateName())) { - bindings[j++] = new SimpleBinding( - newCurrentStatementMatcher.getPredicateName(), - temp.getPredicate()); - } - if (newCurrentStatementMatcher.getObjectValue() == null && currentVarNames .contains(newCurrentStatementMatcher.getObjectName())) { @@ -363,6 +364,9 @@ private List readStatementsInBulk(Set variableNames) { temp.getObject()); } if (bindings.length == 1) { + if (bindings[0] == null) { + throw new IllegalStateException("Binding is null!"); + } return new SingletonBindingSet(bindings[0].getName(), bindings[0].getValue()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/wrapper/data/ConnectionsGroup.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/wrapper/data/ConnectionsGroup.java index 38461cb1edf..605810c5b49 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/wrapper/data/ConnectionsGroup.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/wrapper/data/ConnectionsGroup.java @@ -13,11 +13,17 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import org.eclipse.rdf4j.common.annotation.InternalUseOnly; import org.eclipse.rdf4j.common.transaction.IsolationLevels; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Resource; +import org.eclipse.rdf4j.model.Statement; +import org.eclipse.rdf4j.model.Value; import org.eclipse.rdf4j.sail.Sail; import org.eclipse.rdf4j.sail.SailConnection; +import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; import org.eclipse.rdf4j.sail.shacl.Stats; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BufferedSplitter; @@ -27,6 +33,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + /** * @apiNote since 3.0. This feature is for internal use only: its existence, signature or behavior may change without * warning from one release to the next. @@ -52,6 +61,11 @@ public class ConnectionsGroup implements AutoCloseable { // used to cache Select plan nodes so that we don't query a store for the same data during the same validation step. private final Map nodeCache = new ConcurrentHashMap<>(); + private final Cache INTERNED_VALUE_CACHE = CacheBuilder.newBuilder() + .concurrencyLevel(Runtime.getRuntime().availableProcessors() * 2) + .maximumSize(10000) + .build(); + public ConnectionsGroup(SailConnection baseConnection, SailConnection previousStateConnection, Sail addedStatements, Sail removedStatements, Stats stats, RdfsSubClassOfReasonerProvider rdfsSubClassOfReasonerProvider, @@ -95,6 +109,67 @@ public SailConnection getRemovedStatements() { return removedStatements; } + public enum StatementPosition { + subject, + predicate, + object + } + + /** + * This method is a performance optimization for converting a more general value object, like RDF.TYPE, to the + * specific Value object that the underlying sail would use for that node. It uses a cache to avoid querying the + * store for the same value multiple times during the same validation. + * + * @param value the value object to be converted + * @param statementPosition the position of the statement (subject, predicate, or object) + * @param connection the SailConnection used to retrieve the specific Value object + * @param the type of the value + * @return the specific Value object used by the underlying sail, or the original value if no specific Value is + * found + * @throws SailException if an error occurs while retrieving the specific Value object + */ + public T getSailSpecificValue(T value, StatementPosition statementPosition, + SailConnection connection) { + try { + + Value t = INTERNED_VALUE_CACHE.get(value, () -> { + + switch (statementPosition) { + case subject: + try (var statements = connection.getStatements(((Resource) value), null, null, false).stream()) { + Resource ret = statements.map(Statement::getSubject).findAny().orElse(null); + if (ret == null) { + return value; + } + return ret; + } + case predicate: + try (var statements = connection.getStatements(null, ((IRI) value), null, false).stream()) { + IRI ret = statements.map(Statement::getPredicate).findAny().orElse(null); + if (ret == null) { + return value; + } + return ret; + } + case object: + try (var statements = connection.getStatements(null, null, value, false).stream()) { + Value ret = statements.map(Statement::getObject).findAny().orElse(null); + if (ret == null) { + return value; + } + return ret; + } + } + + throw new IllegalStateException("Unknown statement position: " + statementPosition); + + }); + return ((T) t); + } catch (ExecutionException e) { + throw new SailException(e); + } + } + @Override public void close() { if (addedStatements != null) { @@ -143,9 +218,15 @@ public PlanNode getCachedNodeFor(PlanNode planNode) { } + /** + * Returns the RdfsSubClassOfReasoner if it is enabled. If it is not enabled this method will return null. + * + * @return RdfsSubClassOfReasoner or null + */ public RdfsSubClassOfReasoner getRdfsSubClassOfReasoner() { - if (rdfsSubClassOfReasonerProvider == null) + if (rdfsSubClassOfReasonerProvider == null) { return null; + } return rdfsSubClassOfReasonerProvider.getRdfsSubClassOfReasoner(); } diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java index f62d336424d..9a3d4f8afa4 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java @@ -11,7 +11,6 @@ package org.eclipse.rdf4j.sail.shacl; -import static org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.io.File; @@ -84,7 +83,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.params.provider.Arguments; import org.slf4j.Logger; @@ -111,9 +109,16 @@ abstract public class AbstractShaclTest { public static final Set SHAPE_GRAPHS = Set.of(RDF4J.SHACL_SHAPE_GRAPH, RDF4J.NIL, Values.iri("http://example.com/ns#shapesGraph1")); + public static final String INITIAL_DATA_FILE = "initialData.trig"; + private static final Set ignoredTestCases = Set.of( "test-cases/path/oneOrMorePath", + "test-cases/nodeKind/oneOrMorePathComplex", + "test-cases/nodeKind/zeroOrMorePathComplex", + "test-cases/nodeKind/oneOrMorePathSimple", + "test-cases/minCount/oneOrMorePath", "test-cases/path/zeroOrMorePath", + "test-cases/minCount/zeroOrMorePath", "test-cases/path/zeroOrOnePath" ); @@ -224,7 +229,7 @@ private static Stream findTestCases(String testCase, ExpectedResult ba if (files != null) { Optional initialData = Arrays.stream(files) .map(File::getName) - .filter(name -> name.equals("initialData.trig")) + .filter(name -> name.equals(INITIAL_DATA_FILE)) .findAny(); List queries = Arrays.stream(files) .filter(f -> f.getName().endsWith(".rq")) @@ -607,6 +612,11 @@ void referenceImplementationTestCaseValidation(TestCase testCase) { return; } + // the TopBraid SHACL API doesn't support multiple data graphs + if (testCase.testCasePath.startsWith("test-cases/maxCount/simple/invalid/case4/")) { + return; + } + printTestCase(testCase); Dataset shaclDataset = DatasetFactory.create(); diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShapesGraphTest.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShapesGraphTest.java index 13d07f17650..554c127af4a 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShapesGraphTest.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/ShapesGraphTest.java @@ -109,8 +109,8 @@ public void testInvalidUnionGraph() throws Throwable { connection.begin(); connection.add(laura, FOAF.PHONE, Values.literal(1)); - connection.add(laura, FOAF.PHONE, Values.literal(1), data1); - connection.add(laura, FOAF.PHONE, Values.literal(1), data2); + connection.add(laura, FOAF.PHONE, Values.literal(2), data1); + connection.add(laura, FOAF.PHONE, Values.literal(3), data2); connection.commit(); } @@ -120,6 +120,133 @@ public void testInvalidUnionGraph() throws Throwable { } + @Test + public void testValidUnionGraphMinCount() throws Throwable { + + test(repository -> { + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, RDF.TYPE, FOAF.PERSON, data2); + connection.add(laura, FOAF.NAME, Values.literal("Laura"), data2); + connection.commit(); + } + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + + connection.add(laura, FOAF.INTEREST, Values.literal("golf")); + connection.add(laura, FOAF.INTEREST, Values.literal("tennis"), data1); + connection.add(laura, FOAF.INTEREST, Values.literal("chess"), data2); + + connection.commit(); + } + + }); + + } + + @Test + public void testInvalidUnionGraphMinCount() throws Throwable { + + test(repository -> { + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, RDF.TYPE, FOAF.PERSON, data2); + connection.add(laura, FOAF.NAME, Values.literal("Laura"), data2); + connection.commit(); + } + + assertThrows(RepositoryException.class, () -> { + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + + connection.add(laura, FOAF.INTEREST, Values.literal("golf")); + connection.add(laura, FOAF.INTEREST, Values.literal("golf"), data1); + connection.add(laura, FOAF.INTEREST, Values.literal("golf"), data2); + + connection.commit(); + } + }); + + }); + + } + + @Test + public void testInvalidUnionGraphMinCountSparql() throws Throwable { + + test(repository -> { + + assertThrows(RepositoryException.class, () -> { + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(ShaclSail.TransactionSettings.ValidationApproach.Bulk); + connection.add(laura, RDF.TYPE, FOAF.PERSON, data2); + connection.add(laura, FOAF.NAME, Values.literal("Laura"), data2); + connection.add(laura, FOAF.INTEREST, Values.literal("golf")); + connection.add(laura, FOAF.INTEREST, Values.literal("golf"), data1); + connection.add(laura, FOAF.INTEREST, Values.literal("golf"), data2); + connection.commit(); + } + }); + + }); + + } + + @Test + public void testValidUnionGraph() throws Throwable { + + test(repository -> { + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, RDF.TYPE, FOAF.PERSON, data2); + connection.add(laura, FOAF.NAME, Values.literal("Laura"), data2); + connection.commit(); + } + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + + connection.add(laura, FOAF.PHONE, Values.literal(1)); + connection.add(laura, FOAF.PHONE, Values.literal(1), data1); + connection.add(laura, FOAF.PHONE, Values.literal(1), data2); + + connection.commit(); + } + + }); + + } + + @Test + public void testValidUnionGraphSparql() throws Throwable { + + test(repository -> { + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, RDF.TYPE, FOAF.PERSON, data2); + connection.add(laura, FOAF.NAME, Values.literal("Laura"), data2); + connection.commit(); + } + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(ShaclSail.TransactionSettings.ValidationApproach.Bulk); + + connection.add(laura, FOAF.PHONE, Values.literal(1)); + connection.add(laura, FOAF.PHONE, Values.literal(1), data1); + connection.add(laura, FOAF.PHONE, Values.literal(1), data2); + + connection.commit(); + } + + }); + + } + @Test public void testInvalidSplitAcrossGraphs() throws Throwable { @@ -210,15 +337,15 @@ public void testDefaultShapesGraph() throws IOException { try (RepositoryConnection connection = repository.getConnection()) { connection.begin(); connection.add(laura, RDF.TYPE, FOAF.PERSON, Values.iri("http://example.org/differentGraph")); - connection.add(laura, FOAF.PHONE, Values.literal(12345678)); - connection.add(laura, FOAF.PHONE, Values.literal(12345678), data2); + connection.add(laura, FOAF.PHONE, Values.literal(1)); + connection.add(laura, FOAF.PHONE, Values.literal(2), data2); connection.commit(); } assertThrows(RepositoryException.class, () -> { try (RepositoryConnection connection = repository.getConnection()) { connection.begin(); - connection.add(laura, FOAF.PHONE, Values.literal(12345678), data1); + connection.add(laura, FOAF.PHONE, Values.literal(3), data1); connection.commit(); } }); @@ -227,6 +354,32 @@ public void testDefaultShapesGraph() throws IOException { } + @Test + public void testDefaultShapesGraph2() throws IOException { + + ShaclSail shaclSail = new ShaclSail(new MemoryStore()); + SailRepository repository = new SailRepository(shaclSail); + + loadShapes(repository); + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, RDF.TYPE, FOAF.PERSON, Values.iri("http://example.org/differentGraph")); + connection.add(laura, FOAF.PHONE, Values.literal(1)); + connection.add(laura, FOAF.PHONE, Values.literal(1), data2); + connection.commit(); + } + + try (RepositoryConnection connection = repository.getConnection()) { + connection.begin(); + connection.add(laura, FOAF.PHONE, Values.literal(1), data1); + connection.commit(); + } + + repository.shutDown(); + + } + private void loadShapes(SailRepository repository) throws IOException { try (SailRepositoryConnection connection = repository.getConnection()) { connection.begin(ShaclSail.TransactionSettings.ValidationApproach.Disabled); @@ -246,7 +399,8 @@ private void test(Consumer testCase) throws Throwable { Values.iri(EX, "peopleKnowHumansShapes"), Values.iri(EX, "mustHaveNameShapes"), Values.iri(EX, "maxFiveAcquaintances"), - Values.iri(EX, "nestedKnowsShouldHaveAge") + Values.iri(EX, "nestedKnowsShouldHaveAge"), + Values.iri(EX, "mustHaveMinThreeInterestsOrNoneAtAll") )); loadShapes(repository); diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/UnknownShapesTest.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/UnknownShapesTest.java index 44175008568..6499bbf185e 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/UnknownShapesTest.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/UnknownShapesTest.java @@ -11,6 +11,7 @@ package org.eclipse.rdf4j.sail.shacl; import java.io.IOException; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -86,6 +87,7 @@ private Set getRelevantLog(int expectedNumberOfItems) { .map(String::trim) .collect(Collectors.toSet()); } while (relevantLog.size() < expectedNumberOfItems); + assert relevantLog.size() == expectedNumberOfItems; return relevantLog; } @@ -104,15 +106,20 @@ public void testComplexPath() throws IOException { } } - Set relevantLog = getRelevantLog(4); + Set relevantLog = getRelevantLog(5).stream() + .sorted() + .collect(Collectors.toCollection(LinkedHashSet::new)); Set expected = Set.of( - "Unsupported SHACL feature detected: InversePath{ ZeroOrMorePath{ SimplePath{ } } }. Shape ignored! a sh:PropertyShape; sh:path [ sh:inversePath [ sh:zeroOrMorePath ] ]; sh:datatype xsd:int .", - "Unsupported SHACL feature detected: AlternativePath{ [SimplePath{ }, ZeroOrOnePath{ SimplePath{ } }, SimplePath{ }] }. Shape ignored! a sh:PropertyShape; sh:path [ sh:alternativePath ( [ sh:oneOrMorePath ] ) ]; sh:nodeKind sh:BlankNodeOrIRI .", + "Unsupported SHACL feature detected: AlternativePath{ [SimplePath{ }, OneOrMorePath{ SimplePath{ } }, SimplePath{ }] }. Shape ignored! a sh:PropertyShape; sh:path [ sh:alternativePath ( [ sh:oneOrMorePath ] ) ]; sh:nodeKind sh:BlankNodeOrIRI .", + "Unsupported SHACL feature detected: AlternativePath{ [SimplePath{ }, ZeroOrMorePath{ SimplePath{ } }, SimplePath{ }] }. Shape ignored! a sh:PropertyShape; sh:path [ sh:alternativePath ( [ sh:zeroOrMorePath ] ) ]; sh:nodeKind sh:BlankNodeOrIRI .", "Unsupported SHACL feature detected: AlternativePath{ [SimplePath{ }, ZeroOrOnePath{ SimplePath{ } }, SimplePath{ }] }. Shape ignored! a sh:PropertyShape; sh:path [ sh:alternativePath ( [ sh:zeroOrOnePath ] ) ]; sh:nodeKind sh:BlankNodeOrIRI .", + "Unsupported SHACL feature detected: InversePath{ ZeroOrMorePath{ SimplePath{ } } }. Shape ignored! a sh:PropertyShape; sh:path [ sh:inversePath [ sh:zeroOrMorePath ] ]; sh:datatype xsd:int .", "Unsupported SHACL feature detected: InversePath{ ZeroOrMorePath{ SimplePath{ } } }. Shape ignored! a sh:PropertyShape; sh:path [ sh:inversePath [ sh:zeroOrMorePath ] ]; sh:minCount 1 ." ); + expected = expected.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new)); + Assertions.assertEquals(expected, relevantLog); shaclRepository.shutDown(); diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java index a72a41c0196..62177aeb736 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/Utils.java @@ -12,7 +12,6 @@ package org.eclipse.rdf4j.sail.shacl; import java.io.BufferedInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/W3cComplianceTest.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/W3cComplianceTest.java index cd428fceae4..ecaf7e3c8f1 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/W3cComplianceTest.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/W3cComplianceTest.java @@ -62,7 +62,8 @@ public class W3cComplianceTest { "/core/path/path-zeroOrOne-001.ttl", "/core/property/qualifiedMinCountDisjoint-001.ttl", "/core/property/qualifiedValueShapesDisjoint-001.ttl", - "/core/property/uniqueLang-002.ttl"); + "/core/property/uniqueLang-002.ttl" + ); public static Stream data() { return getTestFiles().stream() diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/SparqlConstraintsBenchmarkEmpty.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/SparqlConstraintsBenchmarkEmpty.java index 8464583871b..1ecdcc16330 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/SparqlConstraintsBenchmarkEmpty.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/benchmark/SparqlConstraintsBenchmarkEmpty.java @@ -15,12 +15,8 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Model; import org.eclipse.rdf4j.model.Statement; -import org.eclipse.rdf4j.model.impl.SimpleValueFactory; -import org.eclipse.rdf4j.model.vocabulary.RDF; -import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.rio.RDFFormat; diff --git a/core/sail/shacl/src/test/resources/complexPath.trig b/core/sail/shacl/src/test/resources/complexPath.trig index 6156512fe4d..ab26e8df364 100644 --- a/core/sail/shacl/src/test/resources/complexPath.trig +++ b/core/sail/shacl/src/test/resources/complexPath.trig @@ -20,6 +20,7 @@ ex:PersonShape ex:alternativePath , ex:nestedSequencePath , ex:alternativePathZeroOrOne , + ex:alternativePathZeroOrMore , ex:alternativePathOneOrMore . ex:inverseOfWithComplex @@ -47,6 +48,11 @@ ex:alternativePathZeroOrOne sh:path [ sh:alternativePath (ex:father [sh:zeroOrOnePath ex:parent] ex:mother ) ] ; sh:nodeKind sh:BlankNodeOrIRI . +ex:alternativePathZeroOrMore + sh:path [ sh:alternativePath (ex:father [sh:zeroOrMorePath ex:parent] ex:mother ) ] ; + sh:nodeKind sh:BlankNodeOrIRI . + + ex:alternativePathOneOrMore sh:path [ sh:alternativePath (ex:father [sh:oneOrMorePath ex:parent] ex:mother ) ] ; sh:nodeKind sh:BlankNodeOrIRI . diff --git a/core/sail/shacl/src/test/resources/logback-test.xml b/core/sail/shacl/src/test/resources/logback-test.xml index 990f3bb2551..40ced8210b0 100644 --- a/core/sail/shacl/src/test/resources/logback-test.xml +++ b/core/sail/shacl/src/test/resources/logback-test.xml @@ -7,7 +7,7 @@ - + diff --git a/core/sail/shacl/src/test/resources/multipleShapesGraphs.trig b/core/sail/shacl/src/test/resources/multipleShapesGraphs.trig index 6cd2a98ef19..0ca11d3d069 100644 --- a/core/sail/shacl/src/test/resources/multipleShapesGraphs.trig +++ b/core/sail/shacl/src/test/resources/multipleShapesGraphs.trig @@ -5,6 +5,7 @@ @prefix sh: . @prefix xsd: . @prefix rdf4j: . +@prefix rsx: . ex:peopleKnowPeopleShapes { ex:PersonShapeKnowsPerson a sh:NodeShape; @@ -43,6 +44,23 @@ ex:mustHaveNameShapes { ex:data2 sh:shapesGraph ex:mustHaveNameShapes. } +ex:mustHaveMinThreeInterestsOrNoneAtAll { + ex:mustHaveMinThreeInterestsOrNoneAtAll a sh:NodeShape; + sh:targetSubjectsOf foaf:interest; + sh:property [ + sh:path foaf:interest; + sh:minCount 3; + ] . + + [ + a rsx:DataAndShapesGraphLink; + rsx:shapesGraph ex:mustHaveMinThreeInterestsOrNoneAtAll; + rsx:dataGraph rdf4j:nil, ex:data1, ex:data2; + ] +} + + + rdf4j:SHACLShapeGraph { ex:PersonShapeMustHaveName a sh:NodeShape; sh:targetClass foaf:Person; @@ -65,6 +83,7 @@ ex:maxFiveAcquaintances { ex:data2 sh:shapesGraph ex:maxFiveAcquaintances. } + ex:nestedKnowsShouldHaveAge { ex:PersonShapeNestedKnowsShouldHaveAge a sh:NodeShape; sh:targetClass foaf:Person; diff --git a/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig index 54ddd788c91..7fe659e684e 100644 --- a/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig +++ b/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig @@ -8,4 +8,3 @@ @prefix rsx: . ex:validPerson1 ex:info "blue", "red" . - diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query2.rq b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query2.rq new file mode 100644 index 00000000000..4c9c80e4579 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + GRAPH ex:g1 { + ex:validPerson1 ex:ssn "789", "012". + } +} diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/report.ttl new file mode 100644 index 00000000000..24bceadf899 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/invalid/case4/report.ttl @@ -0,0 +1,23 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultPath ex:ssn; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:maxCount 3; + sh:path ex:ssn + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query2.rq b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query2.rq new file mode 100644 index 00000000000..0d4f5d03324 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + GRAPH ex:g1 { + ex:validPerson1 ex:ssn "789", "123". + } +} diff --git a/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/maxCount/simple/valid/case5/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/query1.rq new file mode 100644 index 00000000000..5242e77e52d --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/report.ttl new file mode 100644 index 00000000000..17b75d04990 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case1/report.ttl @@ -0,0 +1,31 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultMessage "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac982; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:message "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:minCount 2; + sh:path _:4e2d4e9d107d42408848b92cc2bcac982 + ] + ] . + +_:4e2d4e9d107d42408848b92cc2bcac982 sh:oneOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query1.rq new file mode 100644 index 00000000000..7354a2d0833 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query2.rq new file mode 100644 index 00000000000..6194108fba0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson2 a ex:Person. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/report.ttl new file mode 100644 index 00000000000..d5fbf1d42da --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case2/report.ttl @@ -0,0 +1,31 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson2; + sh:resultMessage "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac9829; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:message "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:minCount 2; + sh:path _:4e2d4e9d107d42408848b92cc2bcac9829 + ] + ] . + +_:4e2d4e9d107d42408848b92cc2bcac9829 sh:oneOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query2.rq new file mode 100644 index 00000000000..b66cba3559b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/report.ttl new file mode 100644 index 00000000000..1f65bb9b558 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/invalid/case3/report.ttl @@ -0,0 +1,31 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultMessage "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac9848; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:message "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:minCount 2; + sh:path _:4e2d4e9d107d42408848b92cc2bcac9848 + ] + ] . + +_:4e2d4e9d107d42408848b92cc2bcac9848 sh:oneOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/shacl.trig new file mode 100644 index 00000000000..0cfb7bf0586 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/shacl.trig @@ -0,0 +1,18 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + + rdf4j:SHACLShapeGraph { + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path [ sh:oneOrMorePath [sh:alternativePath (ex:ssn ex:socialSecurityNumber) ]]; + sh:minCount 2 ; + sh:message "Requires at least 2 social security numbers", "Trenger minst 2 fødselsnummer"@no-nb, "Requires at least 2 social security numbers"@en ; + ] . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/query1.rq new file mode 100644 index 00000000000..5503d3a67c0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query1.rq new file mode 100644 index 00000000000..7354a2d0833 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query2.rq new file mode 100644 index 00000000000..d83a28ac680 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson2 a ex:Person; + ex:ssn "456". +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query2.rq new file mode 100644 index 00000000000..dcc7172407e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123" . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case3/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query2.rq new file mode 100644 index 00000000000..9e6f58ccaf9 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 a ex:Person . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query3.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query3.rq new file mode 100644 index 00000000000..72033356446 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/query3.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 ex:ssn "123" . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case4/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query1.rq new file mode 100644 index 00000000000..f0f7dff41af --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +[] ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query2.rq new file mode 100644 index 00000000000..10551edc99b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +insert { + ?a a ex:Person; + ex:ssn "456". +} where{ + ?a ex:ssn ?b. +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/oneOrMorePath/valid/case5/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/query1.rq new file mode 100644 index 00000000000..cd0f2c009fe --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/query1.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssnObject1 ex:o1. + +ex:o1 ex:ssnObject2 ex:o2. +ex:o2 ex:ssnObject3 ex:o3. +ex:o3 ex:ssnObject4 ex:o4. + +ex:o4 ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/report.ttl new file mode 100644 index 00000000000..4994d318dcb --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case1/report.ttl @@ -0,0 +1,30 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultMessage "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:resultPath _:8235d18495e54f40834e0436a979b57f2; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:message "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:minCount 2; + sh:path _:8235d18495e54f40834e0436a979b57f2 + ] + ] . + +_:8235d18495e54f40834e0436a979b57f2 rdf:first ex:ssnObject1; + rdf:rest (ex:ssnObject2 ex:ssnObject3 ex:ssnObject4 ex:ssn) . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query1.rq new file mode 100644 index 00000000000..52a62cd1dd1 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query1.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssnObject1 ex:o1. + +ex:o1 ex:ssnObject2 ex:o2. +ex:o2 ex:ssnObject3 ex:o3. +ex:o3 ex:ssnObject4 ex:o4. + +ex:o4 ex:ssn "123", "234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query2.rq new file mode 100644 index 00000000000..3c21c84f463 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { + + ex:o2 ex:ssnObject3 ex:o3. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/report.ttl new file mode 100644 index 00000000000..b1cf96d6afa --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/invalid/case2/report.ttl @@ -0,0 +1,30 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultMessage "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:resultPath _:8235d18495e54f40834e0436a979b57f32; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:message "Requires at least 2 social security numbers"@en, "Trenger minst 2 fødselsnummer"@no-nb, + "Requires at least 2 social security numbers"; + sh:minCount 2; + sh:path _:8235d18495e54f40834e0436a979b57f32 + ] + ] . + +_:8235d18495e54f40834e0436a979b57f32 rdf:first ex:ssnObject1; + rdf:rest (ex:ssnObject2 ex:ssnObject3 ex:ssnObject4 ex:ssn) . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/shacl.trig new file mode 100644 index 00000000000..0047f6c1720 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/shacl.trig @@ -0,0 +1,18 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + + rdf4j:SHACLShapeGraph { + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path (ex:ssnObject1 ex:ssnObject2 ex:ssnObject3 ex:ssnObject4 ex:ssn) ; + sh:minCount 2 ; + sh:message "Requires at least 2 social security numbers", "Trenger minst 2 fødselsnummer"@no-nb, "Requires at least 2 social security numbers"@en ; + ] . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/query1.rq new file mode 100644 index 00000000000..52a62cd1dd1 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/query1.rq @@ -0,0 +1,18 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssnObject1 ex:o1. + +ex:o1 ex:ssnObject2 ex:o2. +ex:o2 ex:ssnObject3 ex:o3. +ex:o3 ex:ssnObject4 ex:o4. + +ex:o4 ex:ssn "123", "234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query1.rq new file mode 100644 index 00000000000..a807e16f57d --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query1.rq @@ -0,0 +1,17 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 ex:ssnObject1 ex:o1. + +ex:o1 ex:ssnObject2 ex:o2. +ex:o2 ex:ssnObject3 ex:o3. +ex:o3 ex:ssnObject4 ex:o4. + +ex:o4 ex:ssn "123", "234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query2.rq new file mode 100644 index 00000000000..703e8569ff7 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/sequencePath/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/query1.rq new file mode 100644 index 00000000000..5242e77e52d --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/report.ttl new file mode 100644 index 00000000000..b451e1d95b2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case1/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98108; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:minCount 3; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98108 + ] + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98108 sh:zeroOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query1.rq new file mode 100644 index 00000000000..7354a2d0833 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query2.rq new file mode 100644 index 00000000000..6194108fba0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson2 a ex:Person. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/report.ttl new file mode 100644 index 00000000000..f98c8a79bab --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case2/report.ttl @@ -0,0 +1,28 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson2; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98127; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape _:4e2d4e9d107d42408848b92cc2bcac98126 + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98126 a sh:PropertyShape; + sh:minCount 3; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98127 . + +_:4e2d4e9d107d42408848b92cc2bcac98127 sh:zeroOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query2.rq new file mode 100644 index 00000000000..b66cba3559b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/report.ttl new file mode 100644 index 00000000000..cfcb429db2f --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/invalid/case3/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98148; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:MinCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:minCount 3; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98148 + ] + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98148 sh:zeroOrMorePath [ + sh:alternativePath (ex:ssn ex:socialSecurityNumber) + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/shacl.trig new file mode 100644 index 00000000000..3667e5751bf --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/shacl.trig @@ -0,0 +1,17 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + + rdf4j:SHACLShapeGraph { + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path [ sh:zeroOrMorePath [sh:alternativePath (ex:ssn ex:socialSecurityNumber) ]]; + sh:minCount 3 ; + ] . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/query1.rq new file mode 100644 index 00000000000..5503d3a67c0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query1.rq new file mode 100644 index 00000000000..7354a2d0833 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +ex:validPerson2 ex:ssn "123". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query2.rq new file mode 100644 index 00000000000..d83a28ac680 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson2 a ex:Person; + ex:ssn "456". +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query2.rq new file mode 100644 index 00000000000..dcc7172407e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123" . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case3/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query1.rq new file mode 100644 index 00000000000..4f6ec8cb08a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:ssn "123", "456". + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query2.rq new file mode 100644 index 00000000000..9e6f58ccaf9 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 a ex:Person . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query3.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query3.rq new file mode 100644 index 00000000000..72033356446 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/query3.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +DELETE DATA { +ex:validPerson1 ex:ssn "123" . + +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case4/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query1.rq new file mode 100644 index 00000000000..f0f7dff41af --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +[] ex:ssn "123". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query2.rq b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query2.rq new file mode 100644 index 00000000000..10551edc99b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +insert { + ?a a ex:Person; + ex:ssn "456". +} where{ + ?a ex:ssn ?b. +} \ No newline at end of file diff --git a/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/minCount/zeroOrMorePath/valid/case5/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/query1.rq new file mode 100644 index 00000000000..4ea35e63b00 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case1/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query1.rq new file mode 100644 index 00000000000..f81594b3c82 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query2.rq new file mode 100644 index 00000000000..99c705005d2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p2 ex:knows2 ex:p3. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case2/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query1.rq new file mode 100644 index 00000000000..ab32ba39da6 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person . + + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query2.rq new file mode 100644 index 00000000000..04cccdf69c8 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 ex:knows1 ex:p2. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case3/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query1.rq new file mode 100644 index 00000000000..047e7654284 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query2.rq new file mode 100644 index 00000000000..30a45209ba2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p3 ex:knows3 "1234". +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case4/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query1.rq new file mode 100644 index 00000000000..f14604ec8c3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query2.rq new file mode 100644 index 00000000000..ce022f32e86 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case5/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/query1.rq new file mode 100644 index 00000000000..b83e90e0b9c --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 [ex:knows2 [ex:knows3 [ex:knows1 ex:p2]]]. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/report.ttl new file mode 100644 index 00000000000..d51742a3640 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/invalid/case6/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:2efb3d13c1264a1e82f94864ebbc900614999; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:2efb3d13c1264a1e82f94864ebbc900614999 + ]; + sh:value "1234" + ] . + +_:2efb3d13c1264a1e82f94864ebbc900614999 sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/shacl.trig new file mode 100644 index 00000000000..cd477663bfe --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/shacl.trig @@ -0,0 +1,19 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + +{ + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path [ sh:oneOrMorePath (ex:knows1 ex:knows2 ex:knows3) ]; + sh:nodeKind sh:BlankNodeOrIRI + ] . + rdf4j:nil sh:shapesGraph rdf4j:nil. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/query1.rq new file mode 100644 index 00000000000..9bdc8b449b3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 ex:p4. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query1.rq new file mode 100644 index 00000000000..5f2bab7c138 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p3 ex:knows3 ex:p4. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query2.rq new file mode 100644 index 00000000000..99c705005d2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p2 ex:knows2 ex:p3. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathComplex/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/query1.rq new file mode 100644 index 00000000000..747c66e1ad5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:knows [ ex:knows [ ex:knows "1234" ]]. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/report.ttl new file mode 100644 index 00000000000..1d245d9721c --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case1/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:e6bc97aad3a0460c9710ad6f22a9570d15019; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:e6bc97aad3a0460c9710ad6f22a9570d15019 + ]; + sh:value "1234" + ] . + +_:e6bc97aad3a0460c9710ad6f22a9570d15019 sh:oneOrMorePath ex:knows . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query1.rq new file mode 100644 index 00000000000..7f561a7eec0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query1.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 ex:knows [ ex:knows [ ex:knows "1234" ]]. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query2.rq new file mode 100644 index 00000000000..2ab72640fb0 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/query2.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person . + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/report.ttl new file mode 100644 index 00000000000..4c04954e16e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/invalid/case2/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:e6bc97aad3a0460c9710ad6f22a9570d15035; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:BlankNodeOrIRI; + sh:path _:e6bc97aad3a0460c9710ad6f22a9570d15035 + ]; + sh:value "1234" + ] . + +_:e6bc97aad3a0460c9710ad6f22a9570d15035 sh:oneOrMorePath ex:knows . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/shacl.trig new file mode 100644 index 00000000000..da372bfd09e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/shacl.trig @@ -0,0 +1,18 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + +{ + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path [ sh:oneOrMorePath ex:knows ]; + sh:nodeKind sh:BlankNodeOrIRI + ] . + rdf4j:nil sh:shapesGraph rdf4j:nil. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/query1.rq new file mode 100644 index 00000000000..205c7e8bd8e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/query1.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:knows [ ex:knows [ ex:knows [] ]]. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query1.rq new file mode 100644 index 00000000000..76d499c1432 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 ex:knows [ ex:knows [ ex:knows [] ]]. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query2.rq new file mode 100644 index 00000000000..c5a47bc073e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query1.rq new file mode 100644 index 00000000000..c0c6f6083d1 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 ex:knows []. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query2.rq new file mode 100644 index 00000000000..ffc6f52d22f --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/query2.rq @@ -0,0 +1,13 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson2 + ex:knows ex:pete ; + a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case3/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/query1.rq new file mode 100644 index 00000000000..6a2561ee83a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:knows ex:peter. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case4/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/query1.rq new file mode 100644 index 00000000000..04b61deb1f8 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { +ex:validPerson1 a ex:Person ; + ex:knows []. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/oneOrMorePathSimple/valid/case5/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/query1.rq new file mode 100644 index 00000000000..4ea35e63b00 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/report.ttl new file mode 100644 index 00000000000..87404bf49b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case1/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98186; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98186 + ]; + sh:value "1234" + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98186 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query1.rq new file mode 100644 index 00000000000..f81594b3c82 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query2.rq new file mode 100644 index 00000000000..99c705005d2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p2 ex:knows2 ex:p3. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/report.ttl new file mode 100644 index 00000000000..5d39bc0a08f --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case2/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98207; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98207 + ]; + sh:value "1234" + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98207 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query1.rq new file mode 100644 index 00000000000..ab32ba39da6 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person . + + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query2.rq new file mode 100644 index 00000000000..04cccdf69c8 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 ex:knows1 ex:p2. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/report.ttl new file mode 100644 index 00000000000..4c7ca7153b7 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case3/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98228; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98228 + ]; + sh:value "1234" + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98228 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query1.rq new file mode 100644 index 00000000000..047e7654284 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query2.rq new file mode 100644 index 00000000000..30a45209ba2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p3 ex:knows3 "1234". +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/report.ttl new file mode 100644 index 00000000000..03dd41ecd87 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case4/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98249; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98249 + ]; + sh:value "1234" + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98249 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query1.rq new file mode 100644 index 00000000000..f14604ec8c3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 "1234". + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query2.rq new file mode 100644 index 00000000000..ce022f32e86 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/report.ttl new file mode 100644 index 00000000000..32204f7992e --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case5/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode ex:validPerson1; + sh:resultPath _:4e2d4e9d107d42408848b92cc2bcac98270; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:4e2d4e9d107d42408848b92cc2bcac98270 + ]; + sh:value "1234" + ] . + +_:4e2d4e9d107d42408848b92cc2bcac98270 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/query1.rq new file mode 100644 index 00000000000..e328f8f9053 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + [] a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/report.ttl new file mode 100644 index 00000000000..8f7d3a5a6cd --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/invalid/case6/report.ttl @@ -0,0 +1,27 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:dataGraph rdf4j:nil; + rsx:shapesGraph rdf4j:nil; + sh:focusNode _:3d9086d5ce836d2b; + sh:resultPath _:c796ffb912304daa9258cc6b992eef4b2; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:nodeKind sh:IRI; + sh:path _:c796ffb912304daa9258cc6b992eef4b2 + ]; + sh:value _:3d9086d5ce836d2b + ] . + +_:c796ffb912304daa9258cc6b992eef4b2 sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/shacl.trig new file mode 100644 index 00000000000..1d1ecfa22eb --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/shacl.trig @@ -0,0 +1,19 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + +{ + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path [ sh:zeroOrMorePath (ex:knows1 ex:knows2 ex:knows3) ]; + sh:nodeKind sh:IRI + ] . + rdf4j:nil sh:shapesGraph rdf4j:nil. + + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/query1.rq new file mode 100644 index 00000000000..9bdc8b449b3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/query1.rq @@ -0,0 +1,15 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p2 ex:knows2 ex:p3. + ex:p3 ex:knows3 ex:p4. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query1.rq new file mode 100644 index 00000000000..5f2bab7c138 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query1.rq @@ -0,0 +1,14 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person ; + ex:knows1 ex:p2. + + ex:p3 ex:knows3 ex:p4. + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query2.rq new file mode 100644 index 00000000000..99c705005d2 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/query2.rq @@ -0,0 +1,10 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:p2 ex:knows2 ex:p3. +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/query1.rq new file mode 100644 index 00000000000..ce022f32e86 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:validPerson1 a ex:Person . + +} diff --git a/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/nodeKind/zeroOrMorePathComplex/valid/case3/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq new file mode 100644 index 00000000000..b1d7c6a0986 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person; + ex:name "en val"@en, "whatever", "other". +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl new file mode 100644 index 00000000000..750a58a5eb3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig new file mode 100644 index 00000000000..0313f7b856a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig @@ -0,0 +1,9 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:person1 a ex:Person ; + ex:name "en val"@en, "whatever" . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq new file mode 100644 index 00000000000..0d73326c533 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq @@ -0,0 +1,22 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT { + GRAPH ex:graph2 { + ex:person2 ex:change ?entity_iri . + } + ?entity_iri ex:name "NONE (string) value updated 2", "NONE (string) value updated 3". +} WHERE { + VALUES ?entity_iri { + ex:person1 + } + ?entity_iri rdf:type ?entity_iri_rdf_type__0 . + + FILTER (?entity_iri_rdf_type__0 = ex:Person) + BIND ('LangStringUniq' as ?entity_iri_ignore__1) . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl new file mode 100644 index 00000000000..750a58a5eb3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig new file mode 100644 index 00000000000..0313f7b856a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig @@ -0,0 +1,9 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:person1 a ex:Person ; + ex:name "en val"@en, "whatever" . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq new file mode 100644 index 00000000000..309455e4185 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 ex:name "other". +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl new file mode 100644 index 00000000000..750a58a5eb3 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig new file mode 100644 index 00000000000..44c5dc4a5a8 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig @@ -0,0 +1,17 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + +rdf4j:SHACLShapeGraph { + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path ex:name; + sh:qualifiedValueShape [sh:datatype xsd:string ; ] ; + sh:qualifiedMaxCount 1 ; + ] . +} diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq new file mode 100644 index 00000000000..9009d9d2f78 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person; + ex:name "en val"@en, "whatever" . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq new file mode 100644 index 00000000000..a77eda769f4 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 ex:name "en val"@en, "whatever" . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq new file mode 100644 index 00000000000..951f75ec122 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person. +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl new file mode 100644 index 00000000000..c0518dc88b5 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/solr/pom.xml b/core/sail/solr/pom.xml index 7d26cafd3f6..c79bfa393e7 100644 --- a/core/sail/solr/pom.xml +++ b/core/sail/solr/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-sail - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-solr RDF4J: Solr Sail Index diff --git a/core/sail/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java b/core/sail/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java index 31cdfb3a440..f04e6cc9cb6 100644 --- a/core/sail/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java +++ b/core/sail/solr/src/main/java/org/eclipse/rdf4j/sail/solr/SolrIndex.java @@ -16,6 +16,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; @@ -317,11 +318,12 @@ protected Iterable query(Resource subject, QuerySpec sp q.addField(SearchFields.URI_FIELD_NAME); } q.addField("score"); + int numDocs = Objects.requireNonNullElse(spec.getNumDocs(), -1); try { if (subject != null) { - response = search(subject, q); + response = search(subject, q, numDocs); } else { - response = search(q); + response = search(q, numDocs); } } catch (SolrServerException e) { throw new IOException(e); @@ -346,10 +348,25 @@ protected Iterable query(Resource subject, QuerySpec sp * @throws IOException */ public QueryResponse search(Resource resource, SolrQuery query) throws SolrServerException, IOException { + return search(resource, query, -1); + } + + /** + * Evaluates the given query only for the given resource. + * + * @param resource + * @param query + * @param numDocs + * @return response + * @throws SolrServerException + * @throws IOException + */ + public QueryResponse search(Resource resource, SolrQuery query, int numDocs) + throws SolrServerException, IOException { // rewrite the query String idQuery = termQuery(SearchFields.URI_FIELD_NAME, SearchFields.getResourceID(resource)); query.setQuery(query.getQuery() + " AND " + idQuery); - return search(query); + return search(query, numDocs); } @Override @@ -553,14 +570,35 @@ public double getY() { * @throws IOException */ public QueryResponse search(SolrQuery query) throws SolrServerException, IOException { - int nDocs; - if (maxDocs > 0) { - nDocs = maxDocs; - } else { + return search(query, -1); + } + + /** + * Evaluates the given query and returns the results as a TopDocs instance. + * + * @param query + * @param numDocs + * @return query response + * @throws SolrServerException + * @throws IOException + */ + public QueryResponse search(SolrQuery query, int numDocs) throws SolrServerException, IOException { + if (numDocs < -1) { + throw new IllegalArgumentException("numDocs should be 0 or greater if defined by the user"); + } + + int size = defaultNumDocs; + if (numDocs >= 0) { + // If the user has set numDocs we will use that. If it is 0 then the implementation may end up throwing an + // exception. + size = Math.min(maxDocs, numDocs); + } + + if (size < 0) { long docCount = client.query(query.setRows(0)).getResults().getNumFound(); - nDocs = Math.max((int) Math.min(docCount, Integer.MAX_VALUE), 1); + size = Math.max((int) Math.min(docCount, maxDocs), 1); } - return client.query(query.setRows(nDocs)); + return client.query(query.setRows(size)); } private SolrQuery prepareQuery(IRI propertyURI, SolrQuery query) { diff --git a/core/sparqlbuilder/pom.xml b/core/sparqlbuilder/pom.xml index 743faede34a..2e589196e67 100644 --- a/core/sparqlbuilder/pom.xml +++ b/core/sparqlbuilder/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sparqlbuilder RDF4J: SparqlBuilder diff --git a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/constraint/Values.java b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/constraint/Values.java new file mode 100644 index 00000000000..e994c0ca8b8 --- /dev/null +++ b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/constraint/Values.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2024 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.sparqlbuilder.constraint; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.sparqlbuilder.core.Variable; +import org.eclipse.rdf4j.sparqlbuilder.graphpattern.GraphPattern; +import org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf; +import org.eclipse.rdf4j.sparqlbuilder.rdf.RdfValue; + +public class Values implements GraphPattern { + Variable[] variables; + RdfValue[][] solutionSequence; + + private static final RdfValue UNDEF = new RdfValue() { + @Override + public String getQueryString() { + return "UNDEF"; + } + }; + + public Values(Variable[] variables, RdfValue[][] solutionSequence) { + Objects.requireNonNull(solutionSequence); + Objects.requireNonNull(solutionSequence); + if (variables.length == 0) { + throw new IllegalArgumentException("no variables provided for VALUES clause"); + } + if (solutionSequence.length == 0 + || solutionSequence[0] == null + || solutionSequence[0].length == 0) { + throw new IllegalArgumentException("no values provided for VALUES clause"); + } + if (solutionSequence[0].length != variables.length) { + throw new IllegalArgumentException( + solutionSequence[0].length + + " values provided for " + + variables.length + + variables); + } + this.solutionSequence = solutionSequence; + this.variables = variables; + } + + @Override + public String getQueryString() { + StringBuilder sb = new StringBuilder(); + String parOpen = this.variables.length > 1 ? "( " : ""; + String parClose = this.variables.length > 1 ? ") " : ""; + sb.append("VALUES ").append(parOpen); + for (int i = 0; i < variables.length; i++) { + sb.append(variables[i].getQueryString()).append(" "); + } + sb.append(parClose).append("{").append(System.lineSeparator()); + for (int i = 0; i < solutionSequence.length; i++) { + sb.append(" ").append(parOpen); + for (int j = 0; j < solutionSequence[i].length; j++) { + sb.append(solutionSequence[i][j].getQueryString()).append(" "); + } + sb.append(parClose).append(System.lineSeparator()); + } + sb.append("}").append(System.lineSeparator()); + return sb.toString(); + } + + public static VariablesBuilder builder() { + return new Builder(); + } + + public static class Builder implements VariablesBuilder, ValuesBuilder { + public Builder() { + } + + private List variables = new ArrayList<>(); + + private List> values = new ArrayList<>(); + + private List currentValues = new ArrayList<>(); + + @Override + public VariablesBuilder variables(Variable... variable) { + Arrays.stream(variable).forEach(this.variables::add); + return this; + } + + /** + * Provide another value. This will fill up the current solution sequence. If this value is the last one (i.e. + * the solution sequence now is of the same length as the list of variables), the current solution sequence is + * recorded and a new solution sequence begins. + * + * @param value + * @return + */ + @Override + public ValuesBuilder value(RdfValue value) { + this.currentValues.add(valueOrUndef(value)); + if (currentValues.size() >= variables.size()) { + this.values.add(currentValues); + currentValues = new ArrayList<>(); + } + return this; + } + + @Override + public ValuesBuilder values(RdfValue... values) { + if (this.variables.size() == 1) { + for (int i = 0; i < values.length; i++) { + this.values.add(List.of(valueOrUndef(values[i]))); + } + } else if (this.variables.size() == values.length) { + this.values.add(Stream.of(values).map(Values::valueOrUndef).collect(Collectors.toList())); + } else { + throw new IllegalArgumentException( + "Provided list of values must match length of variables, or there must be only one variable."); + } + return this; + } + + @Override + public ValuesBuilder values(Collection values) { + return values(values.toArray(i -> new RdfValue[i])); + } + + @Override + public ValuesBuilder iriValue(IRI value) { + return value(Rdf.iri(value)); + } + + @Override + public ValuesBuilder iriValues(IRI... values) { + return values(Stream.of(values).map(Rdf::iri).toArray(i -> new RdfValue[i])); + } + + @Override + public ValuesBuilder iriValues(Collection values) { + return iriValues(values.toArray(i -> new IRI[i])); + } + + @Override + public Values build() { + if (this.values.isEmpty()) { + throw new IllegalArgumentException("No values provided"); + } + if (!this.currentValues.isEmpty()) { + throw new IllegalArgumentException( + "Current solution sequence is not finished - you added too few or too many values."); + } + RdfValue[][] values = new RdfValue[this.values.size()][this.variables.size()]; + for (int i = 0; i < this.values.size(); i++) { + List current = this.values.get(i); + if (current.size() != this.variables.size()) { + throw new IllegalArgumentException( + String.format( + "You provided $d values for $d variables", + current.size(), + this.variables.size())); + } + for (int j = 0; j < current.size(); j++) { + values[i][j] = current.get(j); + } + } + return new Values(this.variables.toArray(size -> new Variable[size]), values); + } + } + + public interface VariablesBuilder { + + public VariablesBuilder variables(Variable... variable); + + public ValuesBuilder value(RdfValue value); + + public ValuesBuilder values(RdfValue... values); + + public ValuesBuilder values(Collection values); + + public ValuesBuilder iriValue(IRI value); + + public ValuesBuilder iriValues(IRI... values); + + public ValuesBuilder iriValues(Collection values); + } + + public interface ValuesBuilder { + public ValuesBuilder value(RdfValue value); + + public ValuesBuilder values(RdfValue... values); + + public ValuesBuilder values(Collection values); + + public ValuesBuilder iriValue(IRI value); + + public ValuesBuilder iriValues(IRI... values); + + public ValuesBuilder iriValues(Collection values); + + public Values build(); + } + + private static RdfValue valueOrUndef(RdfValue value) { + if (value == null) { + return UNDEF; + } + return value; + } + +} diff --git a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/core/query/Query.java b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/core/query/Query.java index 88992a7e152..ff56465530f 100644 --- a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/core/query/Query.java +++ b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/core/query/Query.java @@ -12,8 +12,10 @@ package org.eclipse.rdf4j.sparqlbuilder.core.query; import java.util.Optional; +import java.util.function.Consumer; import org.eclipse.rdf4j.sparqlbuilder.constraint.Expression; +import org.eclipse.rdf4j.sparqlbuilder.constraint.Values; import org.eclipse.rdf4j.sparqlbuilder.core.Dataset; import org.eclipse.rdf4j.sparqlbuilder.core.From; import org.eclipse.rdf4j.sparqlbuilder.core.GroupBy; @@ -45,6 +47,7 @@ public abstract class Query> implements QueryElement { protected Optional groupBy = Optional.empty(); protected Optional orderBy = Optional.empty(); protected Optional having = Optional.empty(); + protected Optional values = Optional.empty(); protected int limit = -1, offset = -1, varCount = -1, bnodeCount = -1; /** @@ -201,6 +204,13 @@ public T offset(int offset) { return (T) this; } + public T values(Consumer valuesConfigurer) { + Values.Builder builder = (Values.Builder) Values.builder(); + valuesConfigurer.accept(builder); + this.values = Optional.of(builder.build()); + return (T) this; + } + /** * A shortcut. Each call to this method returns a new {@link Variable} that is unique (i.e., has a unique alias) to * this query instance. @@ -246,7 +256,7 @@ public String getQueryString() { if (offset >= 0) { query.append(OFFSET + " ").append(offset).append("\n"); } - + SparqlBuilderUtils.appendAndNewlineIfPresent(values, query); return query.toString(); } } diff --git a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GraphPattern.java b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GraphPattern.java index 2dc8c7d680c..8be610acf3e 100644 --- a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GraphPattern.java +++ b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GraphPattern.java @@ -11,7 +11,10 @@ package org.eclipse.rdf4j.sparqlbuilder.graphpattern; +import java.util.function.Consumer; + import org.eclipse.rdf4j.sparqlbuilder.constraint.Expression; +import org.eclipse.rdf4j.sparqlbuilder.constraint.Values; import org.eclipse.rdf4j.sparqlbuilder.core.QueryElement; /** @@ -42,6 +45,12 @@ default GraphPattern and(GraphPattern... patterns) { return GraphPatterns.and(this).and(patterns); } + default GraphPattern values(Consumer valuesConfigurer) { + Values.Builder valuesBuilder = (Values.Builder) Values.builder(); + valuesConfigurer.accept(valuesBuilder); + return GraphPatterns.and(this).and(valuesBuilder.build()); + } + /** * Convert this graph pattern into an alternative graph pattern, combining this graph pattern with the given * patterns:
diff --git a/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/BaseExamples.java b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/BaseExamples.java index 69c22345e30..6b7ad53aeaf 100644 --- a/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/BaseExamples.java +++ b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/BaseExamples.java @@ -90,10 +90,7 @@ public boolean matches(Object item) { @Override public void describeTo(Description description) { description.appendText( - "To match the following String after lowercasing, removal of newlines and whitespaces.\n"); - description.appendText("\nHint: first difference: " + aroundString + "\n"); - description.appendText( - "Expected: was \"" + expected.replaceAll("\n", "\\\\n").replaceAll("\\s+", " ") + "\""); + "\"" + expected + "\" (ignoring case, whitespace and newlines)"); } }); } diff --git a/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/sparql11spec/Section10Test.java b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/sparql11spec/Section10Test.java new file mode 100644 index 00000000000..ed429c169d5 --- /dev/null +++ b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/examples/sparql11spec/Section10Test.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2024 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.sparqlbuilder.examples.sparql11spec; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.eclipse.rdf4j.sparqlbuilder.constraint.Expressions.notEquals; +import static org.eclipse.rdf4j.sparqlbuilder.core.SparqlBuilder.prefix; +import static org.eclipse.rdf4j.sparqlbuilder.core.SparqlBuilder.var; +import static org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf.iri; + +import org.eclipse.rdf4j.model.vocabulary.DC; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.model.vocabulary.RDF; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.sparqlbuilder.constraint.Expressions; +import org.eclipse.rdf4j.sparqlbuilder.constraint.Values; +import org.eclipse.rdf4j.sparqlbuilder.core.Prefix; +import org.eclipse.rdf4j.sparqlbuilder.core.SparqlBuilder; +import org.eclipse.rdf4j.sparqlbuilder.core.Variable; +import org.eclipse.rdf4j.sparqlbuilder.core.query.Queries; +import org.eclipse.rdf4j.sparqlbuilder.examples.BaseExamples; +import org.eclipse.rdf4j.sparqlbuilder.graphpattern.GraphPattern; +import org.eclipse.rdf4j.sparqlbuilder.graphpattern.TriplePattern; +import org.eclipse.rdf4j.sparqlbuilder.rdf.Iri; +import org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf; +import org.eclipse.rdf4j.sparqlbuilder.rdf.RdfObject; +import org.junit.jupiter.api.Test; + +public class Section10Test extends BaseExamples { + private final Prefix rdfs = SparqlBuilder.prefix("rdfs", iri(RDFS.NS.getName())); + private final Prefix dc = SparqlBuilder.prefix("dc", iri(DC_NS)); + private final Prefix foaf = SparqlBuilder.prefix("foaf", iri(FOAF_NS)); + private final Prefix base = SparqlBuilder.prefix("", iri("http://example/")); + private final Prefix ex = prefix("ex", iri("http://example/")); + private final Prefix rdf = prefix("rdf", iri(RDF.NAMESPACE)); + + private final Prefix prefixBook = prefix("", iri("http://example.org/book/")); + private final Prefix ns = prefix("ns", iri("http://example.org/ns#")); + private final Variable displayString = var("displayString"); + private final Variable x = var("x"); + + private final Variable book = var("book"); + private final Variable title = var("title"); + private final Variable price = var("price"); + + private final Variable name = var("name"); + private final Variable y = var("y"); + private final Variable z = var("z"); + private final Variable ancestor = var("ancestor"); + private final Variable type = var("type"); + private final Variable p = var("p"); + private final Variable v = var("v"); + private final Variable element = var("element"); + private final Variable s = var("s"); + private final Variable total = var("total"); + private final Variable person = var("person"); + private final Iri property = base.iri("property"); + private final Iri me = iri("#me"); + private final Iri thing = iri("http://example/thing"); + private final Iri book1 = base.iri("book1"); + private final Iri book3 = base.iri("book3"); + private final Iri order = base.iri("order"); + private final Iri mailto = iri("mailto:alice@example"); + private final Iri list = base.iri("list"); + + @Test + public void example_10_2_1__two_vars_two_solutions_one_undef() { + Values values = Values.builder() + .variables(x, y) + .values(base.iri("uri1"), Rdf.literalOf(1)) + .values(base.iri("uri2"), null) + .build(); + String str = values.getQueryString(); + assertThat(str).is(stringEqualsIgnoreCaseAndWhitespace( + "VALUES (?x ?y) {\n" + + " (:uri1 1)\n" + + " (:uri2 UNDEF)\n" + + "}" + )); + } + + @Test + public void example_10_2_1__one_var_two_solutions() { + Values values = Values.builder().variables(z).value(Rdf.literalOf("abc")).value(Rdf.literalOf("def")).build(); + String str = values.getQueryString(); + assertThat(str).is(stringEqualsIgnoreCaseAndWhitespace( + "VALUES ?z { \"abc\" \"def\" }" + )); + } + + @Test + public void example_10_2_2__values__in__graphpattern() { + String str = Queries.SELECT(book, title, price) + .prefix(dc, prefixBook, ns) + .where(Values.builder() + .variables(book) + .values(book1, book3) + .build() + .and(book.has(dc.iri("title"), title) + .andHas(ns.iri("price"), price))) + .getQueryString(); + assertThat(str).is(stringEqualsIgnoreCaseAndWhitespace( + "PREFIX dc: \n" + + "\tPREFIX : \n" + + "\tPREFIX ns: \n" + + "\n" + + "\tSELECT ?book ?title ?price\n" + + "WHERE {\n" + + "\t\tVALUES ?book { :book1 :book3 }\n" + + " ?book dc:title ?title ;\n" + + "\t\tns:price ?price .\n" + + "\t}" + )); + } + + @Test + public void example_10_2_2__values__at__end() { + String str = Queries.SELECT(book, title, price) + .prefix(dc, prefixBook, ns) + .where(book.has(dc.iri("title"), title) + .andHas(ns.iri("price"), price)) + .values(v -> v + .variables(book, title) + .values(null, Rdf.literalOf("SPARQL Tutorial")) + .values(prefixBook.iri("book2"), null)) + .getQueryString(); + assertThat(str).is(stringEqualsIgnoreCaseAndWhitespace( + "PREFIX dc: \n" + + "PREFIX : \n" + + "PREFIX ns: \n" + + "\n" + + "SELECT ?book ?title ?price\n" + + "WHERE {\n" + + " ?book dc:title ?title ;\n" + + " ns:price ?price .\n" + + "}\n" + + "VALUES (?book ?title)\n" + + "{ (UNDEF \"SPARQL Tutorial\")\n" + + " (:book2 UNDEF)\n" + + "}" + )); + + } + +} diff --git a/core/spin/pom.xml b/core/spin/pom.xml index cd6e4901b0e..b80e9d40e04 100644 --- a/core/spin/pom.xml +++ b/core/spin/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-spin RDF4J: SPIN diff --git a/core/storage/pom.xml b/core/storage/pom.xml index ff776744e88..6775e4bf837 100644 --- a/core/storage/pom.xml +++ b/core/storage/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-core - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-storage RDF4J: Storage Libraries diff --git a/docker/Dockerfile-jetty b/docker/Dockerfile-jetty new file mode 100644 index 00000000000..b2f3e93d915 --- /dev/null +++ b/docker/Dockerfile-jetty @@ -0,0 +1,36 @@ +# Temp to reduce image size +FROM ubuntu:jammy AS temp + +RUN apt-get clean && apt-get update && apt-get install -y unzip + + +COPY ignore/rdf4j.zip /tmp/rdf4j.zip + +WORKDIR /tmp + +RUN unzip -q /tmp/rdf4j.zip + +# Final workbench +FROM jetty:9-jre17-eclipse-temurin +LABEL org.opencontainers.image.authors="Bart Hanssens (bart.hanssens@bosa.fgov.be)" + +USER root + +ENV JAVA_OPTIONS="-Dorg.eclipse.rdf4j.appdata.basedir=/var/rdf4j -Dorg.eclipse.rdf4j.rio.jsonld_secure_mode=false" +ENV JETTY_MODULES="server,bytebufferpool,threadpool,security,servlet,webapp,ext,plus,deploy,annotations,http,jsp,jstl" + +COPY --from=temp /tmp/eclipse-rdf4j*/war/*.war /var/lib/jetty/webapps/ + +# mimic Tomcat directories for data and logs + +RUN ln -s /usr/local/jetty/logs /var/lib/jetty/logs && \ + mkdir -p /usr/local/jetty/logs /var/rdf4j && \ + chown -R jetty:jetty /usr/local/jetty/logs && \ + chown -R jetty:jetty /var/rdf4j && \ + chown -R jetty:jetty /var/lib/jetty/webapps && \ + java -jar $JETTY_HOME/start.jar --add-to-start=$JETTY_MODULES --approve-all-licenses + +USER jetty + +EXPOSE 8080 + diff --git a/docker/Dockerfile b/docker/Dockerfile-tomcat similarity index 90% rename from docker/Dockerfile rename to docker/Dockerfile-tomcat index 800553f06f6..711e4f7681f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile-tomcat @@ -11,7 +11,7 @@ WORKDIR /tmp RUN unzip -q /tmp/rdf4j.zip # Final workbench -FROM tomcat:8.5-jre11-temurin +FROM tomcat:9-jre17-temurin-jammy MAINTAINER Bart Hanssens (bart.hanssens@bosa.fgov.be) RUN apt-get clean && apt-get update && apt-get upgrade -y && apt-get clean @@ -28,7 +28,7 @@ RUN rm -rf /usr/local/tomcat/webapps/* && \ COPY --from=temp /tmp/eclipse-rdf4j*/war/*.war /usr/local/tomcat/webapps/ -COPY web.xml /usr/local/tomcat/conf/web.xml +COPY tomcat/web.xml /usr/local/tomcat/conf/web.xml USER tomcat diff --git a/docker/README.md b/docker/README.md index 47178c7458a..8a96fa1332c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,8 +1,8 @@ # Eclipse RDF4J server and workbench -Docker image for RDF4J server and workbench, based on the Tomcat 8.5 (JRE 11) image. +Docker image for RDF4J server and workbench, based on a Tomcat 9.0 or Jetty 9.4 (JRE 17) image. -A slightly modified web.mxl is used to fix a known UTF-8 issue +A slightly modified web.mxl is used for Tomcat to fix a known UTF-8 issue (see also http://docs.rdf4j.org/server-workbench-console) ## Port @@ -12,7 +12,7 @@ By default port 8080 is exposed. ## Volumes * RDF4J data will be stored in `/var/rdf4j` - * Tomcat server logs in `/usr/local/tomcat/logs` + * Server logs go to `/usr/local/tomcat/logs` or `/usr/local/jetty/logs` ## Running the docker container @@ -20,21 +20,23 @@ The default java runtime options (-Xmx2g) can be changed by setting the `JAVA_OPTS` environment variable. To avoid data loss between restarts of the docker container, -the exposed volumes can be mapped to existing directories on the host. +the exposed volumes can be mapped to existing (and writable) directories on the host. Example: ``` docker run -d -p 127.0.0.1:8080:8080 -e JAVA_OPTS="-Xms1g -Xmx4g" \ - -v data:/var/rdf4j -v logs:/usr/local/tomcat/logs eclipse/rdf4j + -v /home/rdf4j/data:/var/rdf4j -v /home/rdf4j/logs:/usr/local/tomcat/logs \ + eclipse/rdf4j-workbench ``` -To access your server from another machine you will need to bind to `0.0.0.0` -instead of `127.0.0.1`. - The workbench will be accessible via http://localhost:8080/rdf4j-workbench The server will be accessible via http://localhost:8080/rdf4j-server + +In order to access the workbench and server from another machine, +you will need to bind the docker container to `0.0.0.0` instead of `127.0.0.1`. + ## Security Please note that the RDF4J server in the docker container is not diff --git a/docker/build.sh b/docker/build.sh index d9a7aa6daf2..d128c0661e1 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -5,45 +5,48 @@ set -e CURRENT=$(pwd) cd .. PROJECT_ROOT=$(pwd) +MVN_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml) + cd "$CURRENT" -# clean "ignore" directory -cd ignore -rm -f *.zip +if [ -z ${SKIP_BUILD+x} ]; then + # clean "ignore" directory + cd ignore + rm -f *.zip -cd "$PROJECT_ROOT" + cd "$PROJECT_ROOT" -# remove assembly/target since this is not removed by mvn clean -rm -rf assembly/target/ + # remove assembly/target since this is not removed by mvn clean + rm -rf assembly/target/ -MVN_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml) + #Clean, format and package + echo "Building with Maven" + mvn clean + mvn -T 2C formatter:format impsort:sort && mvn xml-format:xml-format + mvn install -DskipTests + mvn -Passembly package -DskipTests -Dmaven.javadoc.skip=true -Dformatter.skip=true -Dimpsort.skip=true -Dxml-format.skip=true -Djapicmp.skip -Denforcer.skip=true -Dbuildnumber.plugin.phase=none -Danimal.sniffer.skip=true -#Clean, format and package -echo "Building with Maven" -mvn clean -mvn -T 2C formatter:format impsort:sort && mvn xml-format:xml-format -mvn install -DskipTests -mvn -Passembly package -DskipTests -Dmaven.javadoc.skip=true -Dformatter.skip=true -Dimpsort.skip=true -Dxml-format.skip=true -Djapicmp.skip -Denforcer.skip=true -Dbuildnumber.plugin.phase=none -Danimal.sniffer.skip=true + # find .zip file + ZIP=$(find assembly/target/*.zip) + echo "$ZIP" -# find .zip file -ZIP=$(find assembly/target/*.zip) -echo "$ZIP" + # copy zip file into rdf4j.zip + cp "$ZIP" "${CURRENT}/ignore/rdf4j.zip" -# copy zip file into rdf4j.zip -cp "$ZIP" "${CURRENT}/ignore/rdf4j.zip" - -cd "$CURRENT" + cd "$CURRENT" +fi # build -echo "Building docker image" -docker compose build --pull --no-cache +APP_SERVER=${APP_SERVER:-tomcat} +echo "Building docker image for ${APP_SERVER}" -docker tag docker-rdf4j:latest eclipse/rdf4j-workbench:${MVN_VERSION} +docker compose build --pull --no-cache +docker tag docker-rdf4j:latest eclipse/rdf4j-workbench-${APP_SERVER}:${MVN_VERSION} echo " Docker image tagged as: - docker-rdf4j:latest - eclipse/rdf4j-workbench:${MVN_VERSION} + docker-rdf4j:latest + eclipse/rdf4j-workbench-${APP_SERVER}:${MVN_VERSION} To start the workbench and server: docker compose up -d diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 29fd5ddd6ed..63f5490cda4 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,14 +3,17 @@ services: rdf4j: environment: - APP_LOGGING_LEVEL=${APP_LOGGING_LEVEL} + - APP_SERVER=${APP_SERVER:-tomcat} ports: - 127.0.0.1:8080:8080 - build: . + build: + context: . + dockerfile: Dockerfile-${APP_SERVER:-tomcat} restart: always volumes: - rdf4j_data:/var/rdf4j - - rdf4j_logs:/usr/local/tomcat/logs + - rdf4j_logs:/usr/local/${APP_SERVER:-tomcat}/logs volumes: rdf4j_data: - rdf4j_logs: \ No newline at end of file + rdf4j_logs: diff --git a/docker/run.sh b/docker/run.sh index 1f7572be038..6cf1e75aff8 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -2,12 +2,12 @@ set -e ./build.sh -echo "Starting the docker container" +echo "Starting the docker container for ${APP_SERVER}" docker compose up --force-recreate -d # Wait for the server to be ready. Server is ready when the log contains something like "org.apache.catalina.startup.Catalina.start Server startup in 3400 ms". printf '%s' "Waiting for container to be ready" -while ! docker compose logs rdf4j | grep -q "Server startup in"; do +while ! docker compose logs rdf4j | grep -q -e "Server startup in" -e "Started ServerConnector"; do printf '%s' "." # Exit with error if we have looped 30 times (e.g. 30 seconds) ((c++)) && ((c == 30)) && echo "" && docker compose logs | tee && echo "" && docker ps -a | tee && printf '\n%s\n' "Timed out while waiting!" >&2 && exit 1 diff --git a/docker/shutdown.sh b/docker/shutdown.sh new file mode 100755 index 00000000000..adbdf22d585 --- /dev/null +++ b/docker/shutdown.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e + +echo "Stopping the docker container for ${APP_SERVER}" +docker compose down --rmi all -v + diff --git a/docker/web.xml b/docker/tomcat/web.xml similarity index 100% rename from docker/web.xml rename to docker/tomcat/web.xml diff --git a/e2e/run.sh b/e2e/run.sh index 130ed050b92..8fb93afce7e 100755 --- a/e2e/run.sh +++ b/e2e/run.sh @@ -12,23 +12,43 @@ set -e -cd .. -cd docker -./run.sh -./waitForDocker.sh -cd .. -cd e2e +for APP_SERVER in tomcat jetty; do + export APP_SERVER + + cd .. + cd docker + ./run.sh + ./waitForDocker.sh + cd .. + cd e2e -sleep 10 + sleep 10 -if [ ! -d 'node_modules' ]; then - echo "npm ci" - npm ci -fi + if [ ! -d 'node_modules' ]; then + echo "npm ci" + npm ci + fi -docker ps + docker ps -npx playwright install --with-deps # install browsers -npx playwright test -exit $? + npx playwright install --with-deps # install browsers + npx playwright test + + status_npx=$? + + cd .. + cd docker + ./shutdown.sh + + # test for error code + if [ $status_npx -ne 0 ] ; then + echo "Error in E2E test for $APP_SERVER" + exit $status_npx + fi + + echo "E2E test for $APP_SERVER OK" + + # don't redo the whole build process just for making another docker image + export SKIP_BUILD="skip" +done diff --git a/examples/pom.xml b/examples/pom.xml index 5ea69b06efe..5610e589454 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index d9ed1fcd49e..76b87b2bb27 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT pom Eclipse RDF4J An extensible Java framework for RDF and SPARQL @@ -374,7 +374,7 @@ 5.3.37 32.1.3-jre 1.37 - 3.1.0 + 4.0.0 5.9.3 9.4.54.v20240208 4.1.111.Final diff --git a/site/content/documentation/programming/federation.md b/site/content/documentation/programming/federation.md index 93508f262ce..0be4361e3b8 100644 --- a/site/content/documentation/programming/federation.md +++ b/site/content/documentation/programming/federation.md @@ -305,7 +305,8 @@ FedX provides various means for configuration. Configuration settings can be def |leftJoinWorkerThreads | The number of left join worker threads for parallelization, default _10_ | |boundJoinBlockSize | Block size for bound joins, default _25_ | |enforceMaxQueryTime | Max query time in seconds, 0 to disable, default _30_ | -|enableServiceAsBoundJoin | Flag for evaluating a SERVICE expression (contacting non-federation members) using vectored evaluation, default _true_. For today's endpoints it is more efficient to disable vectored evaluation of SERVICE | +|enableServiceAsBoundJoin | Flag for evaluating a SERVICE expression (contacting non-federation members) using vectored evaluation, default _true_. | +|enableOptionalAsBindJoin | Flag for evaluating an OPTIONAL expression using bind join, default _true_. | |includeInferredDefault | whether include inferred statements should be considered, default _true_ | |consumingIterationMax | the max number of results to be consumed by `ConsumingIteration`, default _1000_ | |debugQueryPlan | Print the optimized query execution plan to stdout, default _false_ | diff --git a/site/content/documentation/tools/server-workbench.md b/site/content/documentation/tools/server-workbench.md index 8994b859203..921c1780c73 100644 --- a/site/content/documentation/tools/server-workbench.md +++ b/site/content/documentation/tools/server-workbench.md @@ -15,13 +15,14 @@ RDF4J Server and RDF4J Workbench requires the following software: - Java 11 or newer - A Java Servlet Container that supports Java Servlet API 3.1 and Java Server Pages (JSP) 2.2, or newer. -We recommend using a recent, stable version of [Apache Tomcat](https://tomcat.apache.org/) ([version 9.0](https://tomcat.apache.org/download-90.cgi) at the time of writing). +We recommend using a recent, stable version of [Apache Tomcat](https://tomcat.apache.org/) (version 9.0) or [Jetty](https://jetty.org) (version 9.4) ## Deploying Server and Workbench RDF4J Server is a database management application: it provides HTTP access to RDF4J repositories, exposing them as SPARQL endpoints. RDF4J Server is meant to be accessed by other applications. Apart from some functionality to view the server’s log messages, it doesn’t provide any user oriented functionality. Instead, the user oriented functionality is part of RDF4J Workbench. The Workbench provides a web interface for querying, updating and exploring the repositories of an RDF4J Server. If you have not done so already, you will first need to [download the RDF4J SDK](/download). Both RDF4J Server and RDF4J Workbench can be found in the `war` directory of the SDK. The war-files in this directory need to be deployed in a Java Servlet Container. The deployment process is container-specific, please consult the documentation for your container on how to deploy a web application. For Apache Tomcat, we recommend using the [Tomcat Manager](https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html) to make deployment easier. +For Jetty, it's just a matter of copying the war-files to `$JETTY_BASE\webapps` After you have deployed the RDF4J Workbench webapp, you should be able to access it, by default, at path `http://localhost:8080/rdf4j-workbench`. You can point your browser at this location to verify that the deployment succeeded. @@ -440,7 +441,7 @@ For a list of supported features and more info on how to use SHACL - see [Progra ## Federation -NOTE: new in RDF4J 3.1 +NOTE: since RDF4J 3.1 RDF4J integrates federation support using the [FedX engine](/documentation/programming/federation/). diff --git a/site/themes/hugo-solstice-theme b/site/themes/hugo-solstice-theme index 4685672c230..2b762a0ed31 160000 --- a/site/themes/hugo-solstice-theme +++ b/site/themes/hugo-solstice-theme @@ -1 +1 @@ -Subproject commit 4685672c23094cdaffcbf05ca7b0b1d00c6028c8 +Subproject commit 2b762a0ed3195eb59cf56dd8160a8d8b00e24f36 diff --git a/spring-components/pom.xml b/spring-components/pom.xml index 9ff3131249a..571eebb5bce 100644 --- a/spring-components/pom.xml +++ b/spring-components/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT pom diff --git a/spring-components/rdf4j-spring-demo/pom.xml b/spring-components/rdf4j-spring-demo/pom.xml index c1311b7fe2a..e3376a0dd51 100644 --- a/spring-components/rdf4j-spring-demo/pom.xml +++ b/spring-components/rdf4j-spring-demo/pom.xml @@ -7,7 +7,7 @@ org.eclipse.rdf4j rdf4j-spring-components - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT diff --git a/spring-components/rdf4j-spring/pom.xml b/spring-components/rdf4j-spring/pom.xml index 8a16a1ea55e..b3616e04951 100644 --- a/spring-components/rdf4j-spring/pom.xml +++ b/spring-components/rdf4j-spring/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-spring-components - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-spring RDF4J: Spring diff --git a/spring-components/spring-boot-sparql-web/pom.xml b/spring-components/spring-boot-sparql-web/pom.xml index 4d86156755a..222e9020799 100644 --- a/spring-components/spring-boot-sparql-web/pom.xml +++ b/spring-components/spring-boot-sparql-web/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-spring-components - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-spring-boot-sparql-web RDF4J: Spring boot component for a HTTP sparql server diff --git a/testsuites/benchmark/pom.xml b/testsuites/benchmark/pom.xml index 4bf66ee78da..d2d51f0daa4 100644 --- a/testsuites/benchmark/pom.xml +++ b/testsuites/benchmark/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-benchmark RDF4J: benchmarks diff --git a/testsuites/geosparql/pom.xml b/testsuites/geosparql/pom.xml index 71282dc24b1..3ebb0735c3e 100644 --- a/testsuites/geosparql/pom.xml +++ b/testsuites/geosparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-geosparql-testsuite RDF4J: GeoSPARQL compliance test suite diff --git a/testsuites/lucene/pom.xml b/testsuites/lucene/pom.xml index 5d78d900116..66488c8e819 100644 --- a/testsuites/lucene/pom.xml +++ b/testsuites/lucene/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-lucene-testsuite RDF4J: Lucene Sail Tests @@ -35,5 +35,10 @@ junit-vintage-engine compile + + org.junit.jupiter + junit-jupiter-params + compile + diff --git a/testsuites/lucene/src/main/java/org/eclipse/testsuite/rdf4j/sail/lucene/AbstractLuceneSailTest.java b/testsuites/lucene/src/main/java/org/eclipse/testsuite/rdf4j/sail/lucene/AbstractLuceneSailTest.java index d17d17b353a..53aa2e13261 100644 --- a/testsuites/lucene/src/main/java/org/eclipse/testsuite/rdf4j/sail/lucene/AbstractLuceneSailTest.java +++ b/testsuites/lucene/src/main/java/org/eclipse/testsuite/rdf4j/sail/lucene/AbstractLuceneSailTest.java @@ -11,6 +11,7 @@ package org.eclipse.testsuite.rdf4j.sail.lucene; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.MATCHES; +import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.NUM_DOCS; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.PROPERTY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.QUERY; import static org.eclipse.rdf4j.sail.lucene.LuceneSailSchema.SCORE; @@ -18,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -33,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Literal; @@ -53,6 +56,7 @@ import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.sail.SailRepository; +import org.eclipse.rdf4j.repository.util.Repositories; import org.eclipse.rdf4j.sail.lucene.LuceneSail; import org.eclipse.rdf4j.sail.lucene.LuceneSailSchema; import org.eclipse.rdf4j.sail.memory.MemoryStore; @@ -60,6 +64,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; @Timeout(value = 10, unit = TimeUnit.MINUTES) public abstract class AbstractLuceneSailTest { @@ -107,17 +113,19 @@ public abstract class AbstractLuceneSailTest { protected abstract void configure(LuceneSail sail); - @BeforeEach - public void setUp() { - // set logging, uncomment this to get better logging for debugging - // org.apache.log4j.BasicConfigurator.configure(); - + private void createTestSail(Consumer config) { + if (repository != null) { + repository.shutDown(); + repository = null; + } // setup a LuceneSail MemoryStore memoryStore = new MemoryStore(); // enable lock tracking org.eclipse.rdf4j.common.concurrent.locks.Properties.setLockTrackingEnabled(true); sail = new LuceneSail(); + configure(sail); + config.accept(sail); sail.setBaseSail(memoryStore); // create a Repository wrapping the LuceneSail @@ -139,10 +147,19 @@ public void setUp() { } } + @BeforeEach + public void setUp() throws Exception { + // set logging, uncomment this to get better logging for debugging + // org.apache.log4j.BasicConfigurator.configure(); + createTestSail(lc -> { + }); + } + @AfterEach public void tearDown() throws RepositoryException { if (repository != null) { repository.shutDown(); + repository = null; } org.eclipse.rdf4j.common.concurrent.locks.Properties.setLockTrackingEnabled(false); } @@ -1081,6 +1098,107 @@ public void run() { assertEquals(0, exceptions.size(), "Exceptions occurred during testMultithreadedAdd, see stacktraces above"); } + @ParameterizedTest + @ValueSource(ints = { 1, 2, 3 }) + public void testDefaultNumDocsResult(int numDoc) { + createTestSail(lc -> lc.setParameter(LuceneSail.DEFAULT_NUM_DOCS_KEY, String.valueOf(numDoc))); + Repositories.consumeNoTransaction(repository, conn -> { + try (TupleQueryResult res = conn.prepareTupleQuery( + "SELECT ?Resource {\n" + + " ?Resource <" + MATCHES + "> [\n " + + " <" + QUERY + "> \"one\"\n " + + " ]. } " + ).evaluate()) { + for (int k = 0; k < numDoc; k++) { + assertTrue(res.hasNext(), "missing result #" + k); + res.next(); + } + if (res.hasNext()) { + StringBuilder b = new StringBuilder(); + int r = 0; + do { + b.append("\n#").append(r++).append(res.next()); + } while (res.hasNext()); + fail("can't have more than " + numDoc + " result(s)" + b); + } + } + }); + } + + @ParameterizedTest + @ValueSource(ints = { 1, 2, 3 }) + public void testMaxNumDocsResult(int numDoc) { + createTestSail(lc -> lc.setParameter(LuceneSail.MAX_DOCUMENTS_KEY, String.valueOf(numDoc))); + Repositories.consumeNoTransaction(repository, conn -> { + try (TupleQueryResult res = conn.prepareTupleQuery( + "SELECT ?Resource {\n" + + " ?Resource <" + MATCHES + "> [\n " + + " <" + QUERY + "> \"one\";\n " + + " <" + NUM_DOCS + "> 3;\n " + + " ]. } " + ).evaluate()) { + for (int k = 0; k < numDoc; k++) { + assertTrue(res.hasNext(), "missing result #" + k); + res.next(); + } + if (res.hasNext()) { + StringBuilder b = new StringBuilder(); + int r = 0; + do { + b.append("\n#").append(r++).append(res.next()); + } while (res.hasNext()); + fail("can't have more than " + numDoc + " result(s)" + b); + } + } + }); + } + + @ParameterizedTest + @ValueSource(ints = { 1, 2, 3 }) + public void testNumDocsResult(int numDoc) { + Repositories.consumeNoTransaction(repository, conn -> { + try (TupleQueryResult res = conn.prepareTupleQuery( + "SELECT ?Resource {\n" + + " ?Resource <" + MATCHES + "> [\n " + + " <" + QUERY + "> \"one\";\n " + + " <" + NUM_DOCS + "> " + numDoc + ";\n " + + " ]. } " + ).evaluate()) { + for (int k = 0; k < numDoc; k++) { + assertTrue(res.hasNext(), "missing result #" + k); + res.next(); + } + if (res.hasNext()) { + StringBuilder b = new StringBuilder(); + int r = 0; + do { + b.append("\n#").append(r++).append(res.next()); + } while (res.hasNext()); + fail("can't have more than " + numDoc + " result(s)" + b); + } + } + }); + } + + @ParameterizedTest + @ValueSource(ints = { -1, -2, -3 }) + public void testNumDocsResultNegative(int numDocs) { + // assert that negative values cause an assertion error + assertThrows(AssertionError.class, () -> { + Repositories.consumeNoTransaction(repository, conn -> { + try (TupleQueryResult res = conn.prepareTupleQuery( + "SELECT ?Resource {\n" + + " ?Resource <" + MATCHES + "> [\n " + + " <" + QUERY + "> \"one\";\n " + + " <" + NUM_DOCS + "> " + numDocs + ";\n " + + " ]. } " + ).evaluate()) { + assertFalse(res.hasNext()); + } + }); + }); + } + protected void assertQueryResult(String literal, IRI predicate, Resource resultUri) { try (RepositoryConnection connection = repository.getConnection()) { // fire a query for all subjects with a given term diff --git a/testsuites/model/pom.xml b/testsuites/model/pom.xml index f5de1f6f4c6..cc4dc7ab767 100644 --- a/testsuites/model/pom.xml +++ b/testsuites/model/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-model-testsuite RDF4J: Model API testsuite diff --git a/testsuites/pom.xml b/testsuites/pom.xml index 677238976b9..42088f21a4d 100644 --- a/testsuites/pom.xml +++ b/testsuites/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-testsuites pom diff --git a/testsuites/queryresultio/pom.xml b/testsuites/queryresultio/pom.xml index 5051bdbadad..feaf586b953 100644 --- a/testsuites/queryresultio/pom.xml +++ b/testsuites/queryresultio/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-queryresultio-testsuite RDF4J: QueryResultIO testsuite diff --git a/testsuites/repository/pom.xml b/testsuites/repository/pom.xml index e3617f8904b..d58184a0a20 100644 --- a/testsuites/repository/pom.xml +++ b/testsuites/repository/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-repository-testsuite RDF4J: Repository API testsuite diff --git a/testsuites/rio/pom.xml b/testsuites/rio/pom.xml index 223c1ae1fc7..8bab2f967d5 100644 --- a/testsuites/rio/pom.xml +++ b/testsuites/rio/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-rio-testsuite RDF4J: Rio compliance test suite diff --git a/testsuites/sail/pom.xml b/testsuites/sail/pom.xml index ec7afe5d121..4b9b7d6c2d1 100644 --- a/testsuites/sail/pom.xml +++ b/testsuites/sail/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sail-testsuite RDF4J: Sail API testsuite diff --git a/testsuites/sparql/pom.xml b/testsuites/sparql/pom.xml index 1a4e54e0e78..6d81c721943 100644 --- a/testsuites/sparql/pom.xml +++ b/testsuites/sparql/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-testsuites - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-sparql-testsuite RDF4J: SPARQL compliance test suite diff --git a/tools/config/pom.xml b/tools/config/pom.xml index c3d008241cf..c6e819ebcc0 100644 --- a/tools/config/pom.xml +++ b/tools/config/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-config RDF4J: application configuration diff --git a/tools/console/pom.xml b/tools/console/pom.xml index b5f504d25f9..a342f03ad96 100644 --- a/tools/console/pom.xml +++ b/tools/console/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-console RDF4J: Console diff --git a/tools/console/src/main/java/org/eclipse/rdf4j/console/command/Convert.java b/tools/console/src/main/java/org/eclipse/rdf4j/console/command/Convert.java index 70af757cb4e..602cc55f132 100644 --- a/tools/console/src/main/java/org/eclipse/rdf4j/console/command/Convert.java +++ b/tools/console/src/main/java/org/eclipse/rdf4j/console/command/Convert.java @@ -104,7 +104,7 @@ private void convert(String fileFrom, String fileTo) { return; } Optional fmtFrom = Rio.getParserFormatForFileName(fileFrom); - if (!fmtFrom.isPresent()) { + if (fmtFrom.isEmpty()) { writeError("No RDF parser for " + fileFrom); return; } @@ -116,7 +116,7 @@ private void convert(String fileFrom, String fileTo) { return; } Optional fmtTo = Rio.getWriterFormatForFileName(fileTo); - if (!fmtTo.isPresent()) { + if (fmtTo.isEmpty()) { writeError("No RDF writer for " + fileTo); return; } diff --git a/tools/console/src/main/java/org/eclipse/rdf4j/console/command/QueryEvaluator.java b/tools/console/src/main/java/org/eclipse/rdf4j/console/command/QueryEvaluator.java index 06cfde2e29a..af11e6bbd98 100644 --- a/tools/console/src/main/java/org/eclipse/rdf4j/console/command/QueryEvaluator.java +++ b/tools/console/src/main/java/org/eclipse/rdf4j/console/command/QueryEvaluator.java @@ -316,7 +316,7 @@ private QueryResultWriter getQueryResultWriter(Path path, OutputStream out) thro w = new ConsoleQueryResultWriter(consoleIO, getConsoleWidth()); } else { Optional fmt = QueryResultIO.getWriterFormatForFileName(path.toFile().toString()); - if (!fmt.isPresent()) { + if (fmt.isEmpty()) { throw new IllegalArgumentException("No suitable result writer found"); } w = QueryResultIO.createWriter(fmt.get(), out); @@ -342,7 +342,7 @@ private RDFWriter getRDFWriter(Path path, OutputStream out) throws IllegalArgume w = new ConsoleRDFWriter(consoleIO, getConsoleWidth()); } else { Optional fmt = Rio.getWriterFormatForFileName(path.toFile().toString()); - if (!fmt.isPresent()) { + if (fmt.isEmpty()) { throw new IllegalArgumentException("No suitable result writer found"); } w = Rio.createWriter(fmt.get(), out); diff --git a/tools/federation/pom.xml b/tools/federation/pom.xml index b6b1d3f9c30..5430f89d375 100644 --- a/tools/federation/pom.xml +++ b/tools/federation/pom.xml @@ -8,7 +8,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedX.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedX.java index 568ae96d56a..7edb14df9e5 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedX.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedX.java @@ -22,6 +22,8 @@ import org.eclipse.rdf4j.federated.endpoint.Endpoint; import org.eclipse.rdf4j.federated.endpoint.ResolvableEndpoint; import org.eclipse.rdf4j.federated.evaluation.FederationEvaluationStrategyFactory; +import org.eclipse.rdf4j.federated.evaluation.concurrent.DefaultSchedulerFactory; +import org.eclipse.rdf4j.federated.evaluation.concurrent.SchedulerFactory; import org.eclipse.rdf4j.federated.exception.ExceptionUtil; import org.eclipse.rdf4j.federated.exception.FedXException; import org.eclipse.rdf4j.federated.exception.FedXRuntimeException; @@ -64,6 +66,8 @@ public class FedX extends AbstractSail implements RepositoryResolverClient { private FederationEvaluationStrategyFactory strategyFactory; + private SchedulerFactory schedulerFactory = DefaultSchedulerFactory.INSTANCE; + private WriteStrategyFactory writeStrategyFactory; private File dataDir; @@ -96,6 +100,19 @@ public void setFederationEvaluationStrategy(FederationEvaluationStrategyFactory this.strategyFactory = strategyFactory; } + /* package */ SchedulerFactory getSchedulerFactory() { + return schedulerFactory; + } + + /** + * Set the {@link SchedulerFactory}. Can only be done before initialization of the federation + * + * @param schedulerFactory the {@link SchedulerFactory} + */ + public void setSchedulerFactory(SchedulerFactory schedulerFactory) { + this.schedulerFactory = schedulerFactory; + } + /** * * @param writeStrategyFactory the {@link WriteStrategyFactory} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedXConfig.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedXConfig.java index ccdc04552fb..c9535d71fdb 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedXConfig.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FedXConfig.java @@ -13,7 +13,6 @@ import java.util.Optional; import org.eclipse.rdf4j.collection.factory.api.CollectionFactory; -import org.eclipse.rdf4j.collection.factory.impl.DefaultCollectionFactory; import org.eclipse.rdf4j.federated.cache.SourceSelectionCache; import org.eclipse.rdf4j.federated.cache.SourceSelectionCacheFactory; import org.eclipse.rdf4j.federated.cache.SourceSelectionMemoryCache; @@ -48,6 +47,8 @@ public class FedXConfig { private boolean enableServiceAsBoundJoin = true; + private boolean enableOptionalAsBindJoin = true; + private boolean enableMonitoring = false; private boolean isLogQueryPlan = false; @@ -68,7 +69,6 @@ public class FedXConfig { private int consumingIterationMax = 1000; - private CollectionFactory cf = new DefaultCollectionFactory(); /* factory like setters */ /** @@ -244,6 +244,17 @@ public FedXConfig withEnableServiceAsBoundJoin(boolean flag) { return this; } + /** + * Whether OPTIONAL clauses are evaluated using bind join (i.e. with the VALUES clause). Default true + * + * @param flag + * @return the current config. + */ + public FedXConfig withEnableOptionalAsBindJoin(boolean flag) { + this.enableOptionalAsBindJoin = flag; + return this; + } + /** * The cache specification for the {@link SourceSelectionMemoryCache}. If not set explicitly, the * {@link SourceSelectionMemoryCache#DEFAULT_CACHE_SPEC} is used. @@ -326,16 +337,26 @@ public int getBoundJoinBlockSize() { * Returns a flag indicating whether vectored evaluation using the VALUES clause shall be applied for SERVICE * expressions. * - * Default: false + * Default: true * - * Note: for todays endpoints it is more efficient to disable vectored evaluation of SERVICE. - * - * @return whether SERVICE expressions are evaluated using bound joins + * @return whether SERVICE expressions are evaluated using bind joins */ public boolean getEnableServiceAsBoundJoin() { return enableServiceAsBoundJoin; } + /** + * Returns a flag indicating whether bind join evaluation using the VALUES clause shall be applied for OPTIONAL + * expressions. + * + * Default: true + * + * @return whether OPTIONAL expressions are evaluated using bind joins + */ + public boolean isEnableOptionalAsBindJoin() { + return enableOptionalAsBindJoin; + } + /** * Get the maximum query time in seconds used for query evaluation. Applied if {@link QueryManager} is used to * create queries. @@ -485,9 +506,10 @@ public int getConsumingIterationMax() { * * @param cf * @return the current config + * @deprecated unusedO */ + @Deprecated(forRemoval = true) public FedXConfig withCollectionFactory(CollectionFactory cf) { - this.cf = cf; return this; } } diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FederationManager.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FederationManager.java index 263ace78bf0..e2b34c8b708 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FederationManager.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/FederationManager.java @@ -26,6 +26,7 @@ import org.eclipse.rdf4j.federated.evaluation.concurrent.ControlledWorkerScheduler; import org.eclipse.rdf4j.federated.evaluation.concurrent.NamingThreadFactory; import org.eclipse.rdf4j.federated.evaluation.concurrent.Scheduler; +import org.eclipse.rdf4j.federated.evaluation.concurrent.SchedulerFactory; import org.eclipse.rdf4j.federated.evaluation.concurrent.TaskWrapper; import org.eclipse.rdf4j.federated.evaluation.union.ControlledWorkerUnion; import org.eclipse.rdf4j.federated.evaluation.union.SynchronousWorkerUnion; @@ -118,26 +119,28 @@ public void reset() { log.debug("Scheduler for join and union are reset."); } + SchedulerFactory schedulerFactory = federation.getSchedulerFactory(); + Optional taskWrapper = federationContext.getConfig().getTaskWrapper(); if (joinScheduler != null) { joinScheduler.abort(); } - joinScheduler = new ControlledWorkerScheduler<>(federationContext.getConfig().getJoinWorkerThreads(), - "Join Scheduler"); + joinScheduler = schedulerFactory.createJoinScheduler(federationContext, + federationContext.getConfig().getJoinWorkerThreads()); taskWrapper.ifPresent(joinScheduler::setTaskWrapper); if (unionScheduler != null) { unionScheduler.abort(); } - unionScheduler = new ControlledWorkerScheduler<>(federationContext.getConfig().getUnionWorkerThreads(), - "Union Scheduler"); + unionScheduler = schedulerFactory.createUnionScheduler(federationContext, + federationContext.getConfig().getUnionWorkerThreads()); taskWrapper.ifPresent(unionScheduler::setTaskWrapper); if (leftJoinScheduler != null) { leftJoinScheduler.abort(); } - leftJoinScheduler = new ControlledWorkerScheduler<>(federationContext.getConfig().getLeftJoinWorkerThreads(), - "Left Join Scheduler"); + leftJoinScheduler = schedulerFactory.createLeftJoinScheduler(federationContext, + federationContext.getConfig().getLeftJoinWorkerThreads()); taskWrapper.ifPresent(leftJoinScheduler::setTaskWrapper); } diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/algebra/BoundJoinTupleExpr.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/algebra/BoundJoinTupleExpr.java index 68b9ca6e4b0..24290ed89cd 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/algebra/BoundJoinTupleExpr.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/algebra/BoundJoinTupleExpr.java @@ -10,14 +10,14 @@ *******************************************************************************/ package org.eclipse.rdf4j.federated.algebra; -import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBoundJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindJoin; /** * Marker interface indicating that instances are applicable for bound join processing (see - * {@link ControlledWorkerBoundJoin} + * {@link ControlledWorkerBindJoin} * * @author Andreas Schwarte - * @see ControlledWorkerBoundJoin + * @see ControlledWorkerBindJoin */ public interface BoundJoinTupleExpr { diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/endpoint/provider/RemoteRepositoryProvider.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/endpoint/provider/RemoteRepositoryProvider.java index 518a7b65234..52647021032 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/endpoint/provider/RemoteRepositoryProvider.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/endpoint/provider/RemoteRepositoryProvider.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.rdf4j.federated.endpoint.provider; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.eclipse.rdf4j.federated.endpoint.Endpoint; @@ -40,13 +42,19 @@ public Endpoint loadEndpoint(RemoteRepositoryRepositoryInformation repoInfo) } try { + HTTPRepository repo = new HTTPRepository(repositoryServer, repositoryName); + SharedHttpClientSessionManager httpClientSessionManager = (SharedHttpClientSessionManager) repo + .getHttpClientSessionManager(); + HttpClientBuilder httpClientBuilder = HttpClients.custom() .useSystemProperties() + .setDefaultRequestConfig(httpClientSessionManager.getDefaultRequestConfig()) .setMaxConnTotal(20) .setMaxConnPerRoute(20); - ((SharedHttpClientSessionManager) repo.getHttpClientSessionManager()) - .setHttpClientBuilder(httpClientBuilder); + + httpClientSessionManager.setHttpClientBuilder(httpClientBuilder); + try { repo.init(); } finally { diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/FederationEvalStrategy.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/FederationEvalStrategy.java index a3e6237dac3..5dafe137315 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/FederationEvalStrategy.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/FederationEvalStrategy.java @@ -15,10 +15,8 @@ import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; import java.util.stream.Collectors; -import org.eclipse.rdf4j.collection.factory.api.CollectionFactory; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.common.iteration.EmptyIteration; import org.eclipse.rdf4j.common.iteration.SingletonIteration; @@ -39,6 +37,7 @@ import org.eclipse.rdf4j.federated.algebra.FedXZeroLengthPath; import org.eclipse.rdf4j.federated.algebra.FederatedDescribeOperator; import org.eclipse.rdf4j.federated.algebra.FilterExpr; +import org.eclipse.rdf4j.federated.algebra.FilterTuple; import org.eclipse.rdf4j.federated.algebra.FilterValueExpr; import org.eclipse.rdf4j.federated.algebra.HolderNode; import org.eclipse.rdf4j.federated.algebra.NJoin; @@ -53,12 +52,14 @@ import org.eclipse.rdf4j.federated.endpoint.Endpoint; import org.eclipse.rdf4j.federated.evaluation.concurrent.ControlledWorkerScheduler; import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelServiceExecutor; +import org.eclipse.rdf4j.federated.evaluation.iterator.BindLeftJoinIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.FedXPathIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.FederatedDescribeIteration; +import org.eclipse.rdf4j.federated.evaluation.iterator.FilteringIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.SingleBindingSetIteration; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindJoin; import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBoundJoin; import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerJoin; -import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerLeftJoin; import org.eclipse.rdf4j.federated.evaluation.join.SynchronousBoundJoin; import org.eclipse.rdf4j.federated.evaluation.join.SynchronousJoin; import org.eclipse.rdf4j.federated.evaluation.union.ControlledWorkerUnion; @@ -68,6 +69,7 @@ import org.eclipse.rdf4j.federated.evaluation.union.ParallelUnionOperatorTask; import org.eclipse.rdf4j.federated.evaluation.union.SynchronousWorkerUnion; import org.eclipse.rdf4j.federated.evaluation.union.WorkerUnionBase; +import org.eclipse.rdf4j.federated.exception.ExceptionUtil; import org.eclipse.rdf4j.federated.exception.FedXRuntimeException; import org.eclipse.rdf4j.federated.exception.IllegalQueryException; import org.eclipse.rdf4j.federated.optimizer.DefaultFedXCostModel; @@ -97,6 +99,7 @@ import org.eclipse.rdf4j.query.QueryEvaluationException; import org.eclipse.rdf4j.query.algebra.DescribeOperator; import org.eclipse.rdf4j.query.algebra.Join; +import org.eclipse.rdf4j.query.algebra.LeftJoin; import org.eclipse.rdf4j.query.algebra.QueryRoot; import org.eclipse.rdf4j.query.algebra.Service; import org.eclipse.rdf4j.query.algebra.StatementPattern; @@ -108,12 +111,10 @@ import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException; import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedService; import org.eclipse.rdf4j.query.algebra.evaluation.federation.ServiceJoinIterator; -import org.eclipse.rdf4j.query.algebra.evaluation.impl.DefaultEvaluationStrategy; import org.eclipse.rdf4j.query.algebra.evaluation.impl.EvaluationStatistics; import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext; import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy; import org.eclipse.rdf4j.query.algebra.evaluation.iterator.BadlyDesignedLeftJoinIterator; -import org.eclipse.rdf4j.query.algebra.evaluation.iterator.DescribeIteration; import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration; import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ConstantOptimizer; import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.DisjunctiveConstraintOptimizer; @@ -748,10 +749,7 @@ public CloseableIteration evaluate(BindingSet bindings) { if (problemVars.containsAll(bindings.getBindingNames())) { var leftIter = leftPrepared.evaluate(bindings); - ControlledWorkerLeftJoin join = new ControlledWorkerLeftJoin(scheduler, FederationEvalStrategy.this, - leftIter, leftJoin, bindings, leftJoin.getQueryInfo()); - executor.execute(join); - return join; + return executeLeftJoin(scheduler, leftIter, leftJoin, bindings, leftJoin.getQueryInfo()); } else { Set problemVarsClone = new HashSet<>(problemVars); problemVarsClone.retainAll(bindings.getBindingNames()); @@ -815,8 +813,14 @@ public QueryEvaluationStep prepareNaryUnion(NUnion union, QueryEvaluationContext /** * Execute the join in a separate thread using some join executor. * - * Join executors are for instance: - {@link SynchronousJoin} - {@link SynchronousBoundJoin} - - * {@link ControlledWorkerJoin} - {@link ControlledWorkerBoundJoin} + * Join executors are for instance: + * + *

    + *
  • {@link SynchronousJoin}
  • + *
  • {@link SynchronousBoundJoin}
  • + *
  • {@link ControlledWorkerJoin}
  • + *
  • {@link ControlledWorkerBindJoin}
  • + *
* * For endpoint federation use controlled worker bound join, for local federation use controlled worker join. The * other operators are there for completeness. @@ -836,6 +840,21 @@ protected abstract CloseableIteration executeJoin( CloseableIteration leftIter, TupleExpr rightArg, Set joinVariables, BindingSet bindings, QueryInfo queryInfo) throws QueryEvaluationException; + /** + * Execute the left join in a separate thread using some join executor. + * + * @param joinScheduler + * @param leftIter + * @param leftJoin + * @param bindings + * @return the result + * @throws QueryEvaluationException + */ + protected abstract CloseableIteration executeLeftJoin( + ControlledWorkerScheduler joinScheduler, + CloseableIteration leftIter, LeftJoin leftJoin, + BindingSet bindings, QueryInfo queryInfo) throws QueryEvaluationException; + public abstract CloseableIteration evaluateExclusiveGroup( ExclusiveGroup group, BindingSet bindings) throws RepositoryException, MalformedQueryException, QueryEvaluationException; @@ -916,14 +935,70 @@ public abstract CloseableIteration evaluateBoundJoinStatementPattern * @param bindings * @return the result iteration * @throws QueryEvaluationException + * @deprecated with VALUES implementation, control flow goes via + * {@link #evaluateBoundJoinStatementPattern(StatementTupleExpr, List)} */ + @Deprecated(forRemoval = true) public abstract CloseableIteration evaluateGroupedCheck( CheckStatementPattern stmt, final List bindings) throws QueryEvaluationException; + /** + * Evaluate the left bind join for the given {@link StatementTupleExpr} and bindings at the relevant endpoints. + * + * @param stmt + * @param bindings + * @return the result iteration + * @throws QueryEvaluationException + * @see {@link BindLeftJoinIteration} + */ + public CloseableIteration evaluateLeftBoundJoinStatementPattern( + StatementTupleExpr stmt, final List bindings) throws QueryEvaluationException { + // we can omit the bound join handling + if (bindings.size() == 1) { + return evaluate(stmt, bindings.get(0)); + } + + FilterValueExpr filterExpr = null; + if (stmt instanceof FilterTuple) { + filterExpr = ((FilterTuple) stmt).getFilterExpr(); + } + + AtomicBoolean isEvaluated = new AtomicBoolean(false); + String preparedQuery = QueryStringUtil.selectQueryStringBoundJoinVALUES((StatementPattern) stmt, bindings, + filterExpr, isEvaluated, stmt.getQueryInfo().getDataset()); + + CloseableIteration result = null; + try { + result = evaluateAtStatementSources(preparedQuery, stmt.getStatementSources(), stmt.getQueryInfo()); + + // apply filter and/or convert to original bindings + if (filterExpr != null && !isEvaluated.get()) { + result = new BindLeftJoinIteration(result, bindings); // apply conversion + result = new FilteringIteration(filterExpr, result, this); // apply filter + if (!result.hasNext()) { + result.close(); + return new EmptyIteration<>(); + } + } else { + result = new BindLeftJoinIteration(result, bindings); + } + + return result; + } catch (Throwable t) { + if (result != null) { + result.close(); + } + if (t instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + throw ExceptionUtil.toQueryEvaluationException(t); + } + } + /** * Evaluate a SERVICE using vectored evaluation, taking the provided bindings as input. * - * See {@link ControlledWorkerBoundJoin} and {@link FedXConfig#getEnableServiceAsBoundJoin()} + * See {@link ControlledWorkerBindJoin} and {@link FedXConfig#getEnableServiceAsBoundJoin()} * * @param service * @param bindings diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SailFederationEvalStrategy.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SailFederationEvalStrategy.java index dbe6cf8bfcc..9315a4b8feb 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SailFederationEvalStrategy.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SailFederationEvalStrategy.java @@ -27,11 +27,13 @@ import org.eclipse.rdf4j.federated.evaluation.iterator.FilteringIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.GroupedCheckConversionIteration; import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerLeftJoin; import org.eclipse.rdf4j.federated.structures.QueryInfo; import org.eclipse.rdf4j.federated.util.QueryAlgebraUtil; import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.MalformedQueryException; import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.LeftJoin; import org.eclipse.rdf4j.query.algebra.StatementPattern; import org.eclipse.rdf4j.query.algebra.TupleExpr; import org.eclipse.rdf4j.repository.RepositoryException; @@ -119,6 +121,16 @@ public CloseableIteration executeJoin( return join; } + @Override + protected CloseableIteration executeLeftJoin(ControlledWorkerScheduler joinScheduler, + CloseableIteration leftIter, LeftJoin leftJoin, BindingSet bindings, QueryInfo queryInfo) + throws QueryEvaluationException { + ControlledWorkerLeftJoin join = new ControlledWorkerLeftJoin(joinScheduler, this, + leftIter, leftJoin, bindings, queryInfo); + executor.execute(join); + return join; + } + @Override public CloseableIteration evaluateExclusiveGroup( ExclusiveGroup group, BindingSet bindings) diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SparqlFederationEvalStrategy.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SparqlFederationEvalStrategy.java index 0be9600d7c1..68f0012d536 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SparqlFederationEvalStrategy.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/SparqlFederationEvalStrategy.java @@ -17,8 +17,10 @@ import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.common.iteration.EmptyIteration; import org.eclipse.rdf4j.federated.FederationContext; +import org.eclipse.rdf4j.federated.algebra.BoundJoinTupleExpr; import org.eclipse.rdf4j.federated.algebra.CheckStatementPattern; import org.eclipse.rdf4j.federated.algebra.ExclusiveGroup; +import org.eclipse.rdf4j.federated.algebra.FedXService; import org.eclipse.rdf4j.federated.algebra.FilterTuple; import org.eclipse.rdf4j.federated.algebra.FilterValueExpr; import org.eclipse.rdf4j.federated.algebra.StatementTupleExpr; @@ -29,7 +31,11 @@ import org.eclipse.rdf4j.federated.evaluation.iterator.GroupedCheckConversionIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.InsertBindingsIteration; import org.eclipse.rdf4j.federated.evaluation.iterator.SingleBindingSetIteration; -import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBoundJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindLeftJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerLeftJoin; +import org.eclipse.rdf4j.federated.evaluation.join.JoinExecutorBase; import org.eclipse.rdf4j.federated.exception.ExceptionUtil; import org.eclipse.rdf4j.federated.exception.IllegalQueryException; import org.eclipse.rdf4j.federated.structures.QueryInfo; @@ -37,6 +43,7 @@ import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.MalformedQueryException; import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.LeftJoin; import org.eclipse.rdf4j.query.algebra.StatementPattern; import org.eclipse.rdf4j.query.algebra.TupleExpr; import org.eclipse.rdf4j.repository.RepositoryException; @@ -45,7 +52,7 @@ * Implementation of a federation evaluation strategy which provides some special optimizations for SPARQL (remote) * endpoints. The most important optimization is to used prepared SPARQL Queries that are already created using Strings. *

- * Joins are executed using {@link ControlledWorkerBoundJoin}. + * Joins are executed using {@link ControlledWorkerBindJoin}. *

*

* This implementation uses the SPARQL 1.1 VALUES operator for the bound-join evaluation @@ -111,8 +118,9 @@ public CloseableIteration evaluateBoundJoinStatementPattern( /** * Alternative evaluation implementation using UNION. Nowadays we use a VALUES clause based implementation * - * @deprecated + * @deprecated no longer used */ + @Deprecated(forRemoval = true) protected CloseableIteration evaluateBoundJoinStatementPattern_UNION( StatementTupleExpr stmt, List bindings) throws QueryEvaluationException { @@ -173,13 +181,61 @@ public CloseableIteration executeJoin( TupleExpr rightArg, Set joinVars, BindingSet bindings, QueryInfo queryInfo) throws QueryEvaluationException { - ControlledWorkerBoundJoin join = new ControlledWorkerBoundJoin(joinScheduler, this, leftIter, rightArg, - bindings, queryInfo); + // determine if we can execute the expr as bind join + boolean executeAsBindJoin = false; + if (rightArg instanceof BoundJoinTupleExpr) { + if (rightArg instanceof FedXService) { + executeAsBindJoin = queryInfo.getFederationContext().getConfig().getEnableServiceAsBoundJoin(); + } else { + executeAsBindJoin = true; + } + } + + JoinExecutorBase join; + if (executeAsBindJoin) { + join = new ControlledWorkerBindJoin(joinScheduler, this, leftIter, rightArg, + bindings, queryInfo); + } else { + join = new ControlledWorkerJoin(joinScheduler, this, leftIter, rightArg, bindings, + queryInfo); + } + join.setJoinVars(joinVars); executor.execute(join); return join; } + @Override + protected CloseableIteration executeLeftJoin(ControlledWorkerScheduler joinScheduler, + CloseableIteration leftIter, LeftJoin leftJoin, BindingSet bindings, QueryInfo queryInfo) + throws QueryEvaluationException { + + var rightArg = leftJoin.getRightArg(); + var fedxConfig = queryInfo.getFederationContext().getConfig(); + + // determine if we can execute the expr as bind join + boolean executeAsBindJoin = false; + if (fedxConfig.isEnableOptionalAsBindJoin() && rightArg instanceof BoundJoinTupleExpr) { + if (rightArg instanceof FedXService) { + executeAsBindJoin = false; + } else { + executeAsBindJoin = true; + } + } + + JoinExecutorBase join; + if (executeAsBindJoin) { + join = new ControlledWorkerBindLeftJoin(joinScheduler, this, leftIter, rightArg, + bindings, queryInfo); + } else { + join = new ControlledWorkerLeftJoin(joinScheduler, this, + leftIter, leftJoin, bindings, queryInfo); + } + + executor.execute(join); + return join; + } + @Override public CloseableIteration evaluateExclusiveGroup( ExclusiveGroup group, BindingSet bindings) throws RepositoryException, diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/ControlledWorkerScheduler.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/ControlledWorkerScheduler.java index f677ca46ea4..ea57e5192df 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/ControlledWorkerScheduler.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/ControlledWorkerScheduler.java @@ -11,14 +11,16 @@ package org.eclipse.rdf4j.federated.evaluation.concurrent; import java.util.List; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import org.eclipse.rdf4j.common.annotation.Experimental; import org.eclipse.rdf4j.common.iteration.CloseableIteration; -import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBoundJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindJoin; import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerJoin; import org.eclipse.rdf4j.federated.evaluation.union.ControlledWorkerUnion; import org.eclipse.rdf4j.federated.exception.ExceptionUtil; @@ -34,7 +36,7 @@ * @author Andreas Schwarte * @see ControlledWorkerUnion * @see ControlledWorkerJoin - * @see ControlledWorkerBoundJoin + * @see ControlledWorkerBindJoin */ public class ControlledWorkerScheduler implements Scheduler, TaskWrapperAware { @@ -42,7 +44,9 @@ public class ControlledWorkerScheduler implements Scheduler, TaskWrapperAw private final ExecutorService executor; - private final LinkedBlockingQueue _taskQueue = new LinkedBlockingQueue<>(); + // TODO: in the next major version of RDF4J this final field should be removed. + // Initialization of the executor service should managed the details + private final BlockingQueue _taskQueue; private final int nWorkers; private final String name; @@ -57,7 +61,8 @@ public class ControlledWorkerScheduler implements Scheduler, TaskWrapperAw public ControlledWorkerScheduler(int nWorkers, String name) { this.nWorkers = nWorkers; this.name = name; - this.executor = createExecutorService(); + this._taskQueue = createBlockingQueue(); + this.executor = createExecutorService(nWorkers, name); } /** @@ -112,13 +117,36 @@ public int getTotalNumberOfWorkers() { return nWorkers; } + @Deprecated(forRemoval = true, since = "5.1") // currently unused and this class is internal public int getNumberOfTasks() { return _taskQueue.size(); } - private ExecutorService createExecutorService() { + /** + * Create the {@link BlockingQueue} used for the thread pool. The default implementation creates a + * {@link LinkedBlockingQueue}. + * + * @return + */ + @Experimental + protected BlockingQueue createBlockingQueue() { + return new LinkedBlockingQueue<>(); + } + + /** + * Create the {@link ExecutorService} which is managing the individual {@link ParallelTask}s in a thread pool. The + * default implementation creates a thread pool with a {@link LinkedBlockingQueue}. + * + * The thread pool should be configured to terminate idle threads after a period of time (default: 60s) + * + * @param nWorkers the number of workers in the thread pool + * @param name the base name for threads in the pool + * @return + */ + @Experimental + protected ExecutorService createExecutorService(int nWorkers, String name) { - ThreadPoolExecutor executor = new ThreadPoolExecutor(nWorkers, nWorkers, 60L, TimeUnit.SECONDS, _taskQueue, + ThreadPoolExecutor executor = new ThreadPoolExecutor(nWorkers, nWorkers, 60L, TimeUnit.SECONDS, this._taskQueue, new NamingThreadFactory(name)); executor.allowCoreThreadTimeOut(true); return executor; diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/DefaultSchedulerFactory.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/DefaultSchedulerFactory.java new file mode 100644 index 00000000000..dd063b6191a --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/DefaultSchedulerFactory.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.concurrent; + +import org.eclipse.rdf4j.federated.FederationContext; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * The default {@link SchedulerFactory} + */ +public class DefaultSchedulerFactory implements SchedulerFactory { + + public static final DefaultSchedulerFactory INSTANCE = new DefaultSchedulerFactory(); + + @Override + public ControlledWorkerScheduler createJoinScheduler(FederationContext federationContext, + int nWorkers) { + return new ControlledWorkerScheduler<>(nWorkers, + "Join Scheduler"); + } + + @Override + public ControlledWorkerScheduler createUnionScheduler(FederationContext federationContext, + int nWorkers) { + return new ControlledWorkerScheduler<>(nWorkers, + "Union Scheduler"); + } + + @Override + public ControlledWorkerScheduler createLeftJoinScheduler(FederationContext federationContext, + int nWorkers) { + return new ControlledWorkerScheduler<>(nWorkers, + "Left Join Scheduler"); + } + +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/SchedulerFactory.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/SchedulerFactory.java new file mode 100644 index 00000000000..50c004b35cc --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/concurrent/SchedulerFactory.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.concurrent; + +import org.eclipse.rdf4j.federated.FederationContext; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ControlledWorkerBindLeftJoin; +import org.eclipse.rdf4j.federated.evaluation.join.ParallelBindLeftJoinTask; +import org.eclipse.rdf4j.federated.evaluation.join.ParallelBoundJoinTask; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * Factory for creating {@link ControlledWorkerScheduler} for executing subqueries (e.g. joins) in the background + * + * @see DefaultSchedulerFactory + * @author Andreas Schwarte + */ +public interface SchedulerFactory { + + /** + * Create a {@link ControlledWorkerScheduler} for regular joins (e.g., the sub-queries generated as part of bind + * joins) + * + * @param federationContext + * @param nWorkers + * @return + * @see ControlledWorkerBindJoin + * @see ParallelBoundJoinTask + */ + ControlledWorkerScheduler createJoinScheduler(FederationContext federationContext, int nWorkers); + + /** + * Create a {@link ControlledWorkerScheduler} for unions (e.g., for executing UNION operands in parallel) + * + * @param federationContext + * @param nWorkers + * @return + */ + ControlledWorkerScheduler createUnionScheduler(FederationContext federationContext, int nWorkers); + + /** + * Create a {@link ControlledWorkerScheduler} for left joins (e.g., the sub-queries generated as part of left bind + * joins, i.e. OPTIONAL) + * + * @param federationContext + * @param nWorkers + * @return + * @see ControlledWorkerBindLeftJoin + * @see ParallelBindLeftJoinTask + */ + ControlledWorkerScheduler createLeftJoinScheduler(FederationContext federationContext, int nWorkers); +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BindLeftJoinIteration.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BindLeftJoinIteration.java new file mode 100644 index 00000000000..5b0b61f544a --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BindLeftJoinIteration.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.iterator; + +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet; +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.common.iteration.LookAheadIteration; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.query.Binding; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet; + +/** + * A {@link LookAheadIteration} for processing bind left join results (i.e., result of joining OPTIONAL clauses) + * + * Algorithm: + * + *

    + *
  • execute left bind join using regular bound join query
  • + *
  • process result iteration similar to {@link BoundJoinVALUESConversionIteration}
  • + *
  • remember seen set of bindings (using index) and add original bindings to those, i.e. put to result return all + * non-seen bindings directly from the input
  • + * + * + * @author Andreas Schwarte + */ +public class BindLeftJoinIteration extends LookAheadIteration { + + protected final CloseableIteration iter; + protected final List bindings; + + protected IntHashSet seenBindingIndexes = new IntHashSet(); + protected final ListIterator bindingsIterator; + + public BindLeftJoinIteration(CloseableIteration iter, + List bindings) { + this.iter = iter; + this.bindings = bindings; + this.bindingsIterator = bindings.listIterator(); + } + + @Override + protected BindingSet getNextElement() { + + if (iter.hasNext()) { + var bIn = iter.next(); + int bIndex = ((Literal) bIn.getValue(BoundJoinVALUESConversionIteration.INDEX_BINDING_NAME)).intValue(); + seenBindingIndexes.add(bIndex); + return convert(bIn, bIndex); + } + + while (bindingsIterator.hasNext()) { + if (seenBindingIndexes.contains(bindingsIterator.nextIndex())) { + // the binding was already processed as part of the optional + bindingsIterator.next(); + continue; + } + return bindingsIterator.next(); + } + + return null; + } + + @Override + protected void handleClose() { + iter.close(); + } + + protected BindingSet convert(BindingSet bIn, int bIndex) throws QueryEvaluationException { + QueryBindingSet res = new QueryBindingSet(); + for (Binding b : bIn) { + if (b.getName().equals(BoundJoinVALUESConversionIteration.INDEX_BINDING_NAME)) { + continue; + } + res.addBinding(b); + } + for (Binding bs : bindings.get(bIndex)) { + res.setBinding(bs); + } + return res; + } + +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BoundJoinVALUESConversionIteration.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BoundJoinVALUESConversionIteration.java index c734fe6fea9..9bc71b87dbd 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BoundJoinVALUESConversionIteration.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/iterator/BoundJoinVALUESConversionIteration.java @@ -10,13 +10,13 @@ *******************************************************************************/ package org.eclipse.rdf4j.federated.evaluation.iterator; -import java.util.Iterator; import java.util.List; import org.eclipse.rdf4j.common.iteration.CloseableIteration; import org.eclipse.rdf4j.common.iteration.ConvertingIteration; import org.eclipse.rdf4j.federated.evaluation.SparqlFederationEvalStrategy; import org.eclipse.rdf4j.federated.util.QueryStringUtil; +import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.query.Binding; import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.QueryEvaluationException; @@ -53,10 +53,8 @@ public BoundJoinVALUESConversionIteration(CloseableIteration iter, @Override protected BindingSet convert(BindingSet bIn) throws QueryEvaluationException { QueryBindingSet res = new QueryBindingSet(); - int bIndex = Integer.parseInt(bIn.getBinding(INDEX_BINDING_NAME).getValue().stringValue()); - Iterator bIter = bIn.iterator(); - while (bIter.hasNext()) { - Binding b = bIter.next(); + int bIndex = ((Literal) bIn.getValue(BoundJoinVALUESConversionIteration.INDEX_BINDING_NAME)).intValue(); + for (Binding b : bIn) { if (b.getName().equals(INDEX_BINDING_NAME)) { continue; } diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoin.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoin.java new file mode 100644 index 00000000000..2da2c52a494 --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoin.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2019 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.federated.evaluation.join; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.federated.algebra.CheckStatementPattern; +import org.eclipse.rdf4j.federated.algebra.FedXService; +import org.eclipse.rdf4j.federated.algebra.StatementTupleExpr; +import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ControlledWorkerScheduler; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelExecutor; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTask; +import org.eclipse.rdf4j.federated.structures.QueryInfo; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * Execution of a regular join as bind join. + * + * @author Andreas Schwarte + * @see ControlledWorkerBindJoinBase + */ +public class ControlledWorkerBindJoin extends ControlledWorkerBindJoinBase { + + public ControlledWorkerBindJoin(ControlledWorkerScheduler scheduler, FederationEvalStrategy strategy, + CloseableIteration leftIter, + TupleExpr rightArg, BindingSet bindings, QueryInfo queryInfo) + throws QueryEvaluationException { + super(scheduler, strategy, leftIter, rightArg, bindings, queryInfo); + } + + @Override + protected TaskCreator determineTaskCreator(TupleExpr expr, BindingSet bs) { + final TaskCreator taskCreator; + if (expr instanceof StatementTupleExpr) { + StatementTupleExpr stmt = (StatementTupleExpr) expr; + taskCreator = new BoundJoinTaskCreator(strategy, stmt); + } else if (expr instanceof FedXService) { + taskCreator = new FedXServiceJoinTaskCreator(strategy, (FedXService) expr); + } else { + throw new RuntimeException("Expr is of unexpected type: " + expr.getClass().getCanonicalName() + + ". Please report this problem."); + } + return taskCreator; + } + + protected class BoundJoinTaskCreator implements TaskCreator { + protected final FederationEvalStrategy _strategy; + protected final StatementTupleExpr _expr; + + public BoundJoinTaskCreator( + FederationEvalStrategy strategy, StatementTupleExpr expr) { + super(); + _strategy = strategy; + _expr = expr; + } + + @Override + public ParallelTask getTask(ParallelExecutor control, List bindings) { + return new ParallelBoundJoinTask(control, _strategy, _expr, bindings); + } + } + + @Deprecated(forRemoval = true) + protected class CheckJoinTaskCreator implements TaskCreator { + protected final FederationEvalStrategy _strategy; + protected final CheckStatementPattern _expr; + + public CheckJoinTaskCreator( + FederationEvalStrategy strategy, CheckStatementPattern expr) { + super(); + _strategy = strategy; + _expr = expr; + } + + @Override + public ParallelTask getTask(ParallelExecutor control, List bindings) { + return new ParallelCheckJoinTask(control, _strategy, _expr, bindings); + } + } + + protected class FedXServiceJoinTaskCreator implements TaskCreator { + protected final FederationEvalStrategy _strategy; + protected final FedXService _expr; + + public FedXServiceJoinTaskCreator( + FederationEvalStrategy strategy, FedXService expr) { + super(); + _strategy = strategy; + _expr = expr; + } + + @Override + public ParallelTask getTask(ParallelExecutor control, List bindings) { + return new ParallelServiceJoinTask(control, _strategy, _expr, bindings); + } + } + +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoinBase.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoinBase.java new file mode 100644 index 00000000000..d00477a2adf --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindJoinBase.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.join; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.federated.algebra.BoundJoinTupleExpr; +import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ControlledWorkerScheduler; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelExecutor; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTask; +import org.eclipse.rdf4j.federated.structures.QueryInfo; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for executing joins as bind joins (i.e., the bindings of a block are injected in the SPARQL query as + * VALUES clause). + * + * The number of concurrent threads is controlled by a {@link ControlledWorkerScheduler} which works according to the + * FIFO principle and uses worker threads. + * + * This join cursor blocks until all scheduled tasks are finished, however the result iteration can be accessed from + * different threads to allow for pipelining. + * + * @author Andreas Schwarte + * + */ +public abstract class ControlledWorkerBindJoinBase extends JoinExecutorBase { + + private static final Logger log = LoggerFactory.getLogger(ControlledWorkerBindJoinBase.class); + + protected final ControlledWorkerScheduler scheduler; + + protected final Phaser phaser = new Phaser(1); + + public ControlledWorkerBindJoinBase(ControlledWorkerScheduler scheduler, + FederationEvalStrategy strategy, + CloseableIteration leftIter, + TupleExpr rightArg, BindingSet bindings, QueryInfo queryInfo) + throws QueryEvaluationException { + super(strategy, leftIter, rightArg, bindings, queryInfo); + this.scheduler = scheduler; + } + + @Override + protected void handleBindings() throws Exception { + if (!(rightArg instanceof BoundJoinTupleExpr)) { + String msg = "Right argument is not an applicable expression for bind joins. Was: " + + rightArg.getClass().getCanonicalName(); + log.debug(msg); + throw new QueryEvaluationException(msg); + } + + int nBindingsCfg = this.queryInfo.getFederationContext().getConfig().getBoundJoinBlockSize(); + int totalBindings = 0; // the total number of bindings + TupleExpr expr = rightArg; + + TaskCreator taskCreator = null; + Phaser currentPhaser = phaser; + + int nBindings; + List bindings; + while (!isClosed() && leftIter.hasNext()) { + + // create a new phaser if there are more than 10000 parties + // note: a phaser supports only up to 65535 registered parties + if (currentPhaser.getRegisteredParties() >= 10000) { + currentPhaser = new Phaser(currentPhaser); + } + + // determine the bind join block size + nBindings = getNextBindJoinSize(nBindingsCfg, totalBindings); + + bindings = new ArrayList<>(nBindings); + + int count = 0; + while (!isClosed() && count < nBindings && leftIter.hasNext()) { + var bs = leftIter.next(); + if (taskCreator == null) { + taskCreator = determineTaskCreator(expr, bs); + } + bindings.add(bs); + count++; + } + + totalBindings += count; + + currentPhaser.register(); + scheduler.schedule(taskCreator.getTask(new PhaserHandlingParallelExecutor(this, currentPhaser), bindings)); + } + + leftIter.close(); + + scheduler.informFinish(this); + + if (log.isDebugEnabled()) { + log.debug("JoinStats: left iter of " + getDisplayId() + " had " + totalBindings + " results."); + } + + phaser.awaitAdvanceInterruptibly(phaser.arrive(), queryInfo.getMaxRemainingTimeMS(), TimeUnit.MILLISECONDS); + } + + @Override + public void handleClose() throws QueryEvaluationException { + try { + super.handleClose(); + } finally { + // signal the phaser to close (if currently being blocked) + phaser.forceTermination(); + } + } + + /** + * Return the {@link TaskCreator} for executing the bind join + * + * @param expr + * @param bs + * @return + */ + protected abstract TaskCreator determineTaskCreator(TupleExpr expr, BindingSet bs); + + /** + * Return the size of the next bind join block. + * + * @param configuredBindJoinSize the configured bind join size + * @param totalBindings the current process bindings from the intermediate result set + * @return + */ + protected int getNextBindJoinSize(int configuredBindJoinSize, int totalBindings) { + + /* + * XXX idea: + * + * make nBindings dependent on the number of intermediate results of the left argument. + * + * If many intermediate results, increase the number of bindings. This will result in less remote SPARQL + * requests. + * + */ + + return configuredBindJoinSize; + } + + protected interface TaskCreator { + ParallelTask getTask(ParallelExecutor control, List bindings); + } +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindLeftJoin.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindLeftJoin.java new file mode 100644 index 00000000000..86da1a81048 --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBindLeftJoin.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.join; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.federated.algebra.EmptyStatementPattern; +import org.eclipse.rdf4j.federated.algebra.StatementTupleExpr; +import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ControlledWorkerScheduler; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelExecutor; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTask; +import org.eclipse.rdf4j.federated.structures.QueryInfo; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryEvaluationException; +import org.eclipse.rdf4j.query.algebra.TupleExpr; + +/** + * Bind join implementation for left joins (i.e., OPTIOAL clauses) + * + * @author Andreas Schwarte + */ +public class ControlledWorkerBindLeftJoin extends ControlledWorkerBindJoinBase { + + public ControlledWorkerBindLeftJoin(ControlledWorkerScheduler scheduler, + FederationEvalStrategy strategy, CloseableIteration leftIter, TupleExpr rightArg, + BindingSet bindings, QueryInfo queryInfo) throws QueryEvaluationException { + super(scheduler, strategy, leftIter, rightArg, bindings, queryInfo); + } + + @Override + protected TaskCreator determineTaskCreator(TupleExpr expr, BindingSet bs) { + final TaskCreator taskCreator; + if (expr instanceof StatementTupleExpr) { + StatementTupleExpr stmt = (StatementTupleExpr) expr; + taskCreator = new LeftBoundJoinTaskCreator(strategy, stmt); + } else if (expr instanceof EmptyStatementPattern) { + EmptyStatementPattern stmt = (EmptyStatementPattern) expr; + taskCreator = new EmptyLeftBoundJoinTaskCreator(strategy, stmt); + } else { + throw new RuntimeException("Expr is of unexpected type: " + expr.getClass().getCanonicalName() + + ". Please report this problem."); + } + return taskCreator; + } + + static protected class LeftBoundJoinTaskCreator implements TaskCreator { + protected final FederationEvalStrategy _strategy; + protected final StatementTupleExpr _expr; + + public LeftBoundJoinTaskCreator( + FederationEvalStrategy strategy, StatementTupleExpr expr) { + super(); + _strategy = strategy; + _expr = expr; + } + + @Override + public ParallelTask getTask(ParallelExecutor control, List bindings) { + return new ParallelBindLeftJoinTask(control, _strategy, _expr, bindings); + } + } + + static protected class EmptyLeftBoundJoinTaskCreator implements TaskCreator { + protected final FederationEvalStrategy _strategy; + protected final EmptyStatementPattern _expr; + + public EmptyLeftBoundJoinTaskCreator( + FederationEvalStrategy strategy, EmptyStatementPattern expr) { + super(); + _strategy = strategy; + _expr = expr; + } + + @Override + public ParallelTask getTask(ParallelExecutor control, List bindings) { + return new ParallelEmptyBindLeftJoinTask(control, _strategy, _expr, bindings); + } + } +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBoundJoin.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBoundJoin.java index db939175e6f..062be55ab75 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBoundJoin.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ControlledWorkerBoundJoin.java @@ -44,7 +44,9 @@ * * @author Andreas Schwarte * + * @deprecated replaced with {@link ControlledWorkerBindJoin}l */ +@Deprecated(forRemoval = true) public class ControlledWorkerBoundJoin extends ControlledWorkerJoin { private static final Logger log = LoggerFactory.getLogger(ControlledWorkerBoundJoin.class); diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelBindLeftJoinTask.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelBindLeftJoinTask.java new file mode 100644 index 00000000000..bfabcb87c40 --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelBindLeftJoinTask.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.join; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.federated.algebra.StatementTupleExpr; +import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelExecutor; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTaskBase; +import org.eclipse.rdf4j.query.BindingSet; + +/** + * A {@link ParallelTaskBase} for executing bind left joins. + * + * @author Andreas Schwarte + * @see FederationEvalStrategy#evaluateLeftBoundJoinStatementPattern(StatementTupleExpr, List) + */ +public class ParallelBindLeftJoinTask extends ParallelTaskBase { + + protected final FederationEvalStrategy strategy; + protected final StatementTupleExpr rightArg; + protected final List bindings; + protected final ParallelExecutor joinControl; + + public ParallelBindLeftJoinTask(ParallelExecutor joinControl, FederationEvalStrategy strategy, + StatementTupleExpr expr, List bindings) { + this.strategy = strategy; + this.rightArg = expr; + this.bindings = bindings; + this.joinControl = joinControl; + } + + @Override + public ParallelExecutor getControl() { + return joinControl; + } + + @Override + protected CloseableIteration performTaskInternal() throws Exception { + return strategy.evaluateLeftBoundJoinStatementPattern(rightArg, bindings); + } + +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelCheckJoinTask.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelCheckJoinTask.java index b567d1c91f0..358178e4fa5 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelCheckJoinTask.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelCheckJoinTask.java @@ -24,7 +24,9 @@ * {@link FederationEvalStrategy#evaluateGroupedCheck(CheckStatementPattern, List)} for further details. * * @author Andreas Schwarte + * @deprecated now integrated in {@link ParallelBoundJoinTask} (with VALUES clause) */ +@Deprecated(forRemoval = true) public class ParallelCheckJoinTask extends ParallelTaskBase { protected final FederationEvalStrategy strategy; diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelEmptyBindLeftJoinTask.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelEmptyBindLeftJoinTask.java new file mode 100644 index 00000000000..9a243578384 --- /dev/null +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/evaluation/join/ParallelEmptyBindLeftJoinTask.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated.evaluation.join; + +import java.util.List; + +import org.eclipse.rdf4j.common.iteration.CloseableIteration; +import org.eclipse.rdf4j.federated.algebra.EmptyStatementPattern; +import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelExecutor; +import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTaskBase; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.repository.sparql.federation.CollectionIteration; + +/** + * A {@link ParallelTaskBase} for executing bind left joins, where the join argument is an + * {@link EmptyStatementPattern}. The effective result is that the input bindings from the left operand are passed + * through. + * + * @author Andreas Schwarte + */ +public class ParallelEmptyBindLeftJoinTask extends ParallelTaskBase { + + protected final FederationEvalStrategy strategy; + protected final EmptyStatementPattern rightArg; + protected final List bindings; + protected final ParallelExecutor joinControl; + + public ParallelEmptyBindLeftJoinTask(ParallelExecutor joinControl, FederationEvalStrategy strategy, + EmptyStatementPattern expr, List bindings) { + this.strategy = strategy; + this.rightArg = expr; + this.bindings = bindings; + this.joinControl = joinControl; + } + + @Override + public ParallelExecutor getControl() { + return joinControl; + } + + @Override + protected CloseableIteration performTaskInternal() throws Exception { + // simply return the input bindings (=> the empty statement pattern cannot add results) + return new CollectionIteration(bindings); + } + +} diff --git a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfig.java b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfig.java index 4a7f4dab854..23923a99e42 100644 --- a/tools/federation/src/main/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfig.java +++ b/tools/federation/src/main/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfig.java @@ -135,6 +135,11 @@ public class FedXRepositoryConfig extends AbstractRepositoryImplConfig { */ public static final IRI CONFIG_ENABLE_SERVICE_AS_BOUND_JOIN = vf.createIRI(NAMESPACE, "enableServiceAsBoundJoin"); + /** + * IRI of the property populating {@link FedXConfig#isEnableOptionalAsBindJoin()} + */ + public static final IRI CONFIG_ENABLE_OPTIONAL_AS_BIND_JOIN = vf.createIRI(NAMESPACE, "enableOptionalAsBindJoin"); + /** * IRI of the property populating {@link FedXConfig#isEnableMonitoring()} */ @@ -331,6 +336,9 @@ private void parseFedXConfigInternal(Model m, Resource confNode) throws Reposito Models.objectLiteral(m.getStatements(confNode, CONFIG_ENABLE_SERVICE_AS_BOUND_JOIN, null)) .ifPresent(value -> config.withEnableServiceAsBoundJoin(value.booleanValue())); + Models.objectLiteral(m.getStatements(confNode, CONFIG_ENABLE_OPTIONAL_AS_BIND_JOIN, null)) + .ifPresent(value -> config.withEnableOptionalAsBindJoin(value.booleanValue())); + Models.objectLiteral(m.getStatements(confNode, CONFIG_ENABLE_MONITORING, null)) .ifPresent(value -> config.withEnableMonitoring(value.booleanValue())); @@ -384,6 +392,9 @@ protected void exportFedXConfig(Model model, Resource implNode) { model.add(confNode, CONFIG_ENABLE_SERVICE_AS_BOUND_JOIN, vf.createLiteral(config.getEnableServiceAsBoundJoin())); + model.add(confNode, CONFIG_ENABLE_OPTIONAL_AS_BIND_JOIN, + vf.createLiteral(config.isEnableOptionalAsBindJoin())); + model.add(confNode, CONFIG_ENABLE_MONITORING, vf.createLiteral(config.isEnableMonitoring())); model.add(confNode, CONFIG_LOG_QUERY_PLAN, vf.createLiteral(config.isLogQueryPlan())); diff --git a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BindLeftJoinTests.java b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BindLeftJoinTests.java new file mode 100644 index 00000000000..d19359f5bd7 --- /dev/null +++ b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BindLeftJoinTests.java @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2024 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.federated; + +import java.util.Arrays; +import java.util.Set; + +import org.eclipse.rdf4j.common.iteration.Iterations; +import org.eclipse.rdf4j.model.util.Values; +import org.eclipse.rdf4j.model.vocabulary.FOAF; +import org.eclipse.rdf4j.model.vocabulary.OWL; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.TupleQuery; +import org.eclipse.rdf4j.query.TupleQueryResult; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class BindLeftJoinTests extends SPARQLBaseTest { + + @Override + protected void initFedXConfig() { + + fedxRule.withConfiguration(config -> { + config.withEnableMonitoring(true); + }); + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + public void test_leftBindJoin_basic(boolean bindLeftJoinOptimizationEnabled) throws Exception { + + prepareTest( + Arrays.asList("/tests/basic/data_emptyStore.ttl", "/tests/basic/data_emptyStore.ttl", + "/tests/basic/data_emptyStore.ttl")); + + Repository repo1 = getRepository(1); + Repository repo2 = getRepository(2); + Repository repo3 = getRepository(3); + + Repository fedxRepo = fedxRule.getRepository(); + + fedxRule.setConfig(config -> { + config.withBoundJoinBlockSize(10); + config.withEnableOptionalAsBindJoin(bindLeftJoinOptimizationEnabled); + }); + + // add some persons + try (RepositoryConnection conn = repo1.getConnection()) { + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + conn.add(p, OWL.SAMEAS, otherP); + } + } + + // add names for person 1, 4, 7, ... + try (RepositoryConnection conn = repo2.getConnection()) { + + for (int i = 1; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.NAME, Values.literal("Person " + i)); + } + } + + // add names for person 2, 5, 8, ... + try (RepositoryConnection conn = repo3.getConnection()) { + + for (int i = 2; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.NAME, Values.literal("Person " + i)); + } + } + + try { + // run query which joins results from multiple repos + // for a subset of persons there exist names + try (RepositoryConnection conn = fedxRepo.getConnection()) { + String query = "PREFIX foaf: " + + "SELECT * WHERE { " + + " ?person owl:sameAs ?otherPerson . " + + " OPTIONAL { ?otherPerson foaf:name ?name . } " // # @repo2 and @repo3 + + "}"; + + TupleQuery tupleQuery = conn.prepareTupleQuery(query); + try (TupleQueryResult tqr = tupleQuery.evaluate()) { + var bindings = Iterations.asList(tqr); + + Assertions.assertEquals(30, bindings.size()); + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + + // find the bindingset for the person in the unordered result + BindingSet bs = bindings.stream() + .filter(b -> b.getValue("person").equals(p)) + .findFirst() + .orElseThrow(); + + Assertions.assertEquals(otherP, bs.getValue("otherPerson")); + if (i % 3 == 1 || i % 3 == 2) { + // names from repo 2 or 3 + Assertions.assertEquals("Person " + i, bs.getValue("name").stringValue()); + } else { + // no name for others + Assertions.assertFalse(bs.hasBinding("name")); + } + } + } + + } + + if (bindLeftJoinOptimizationEnabled) { + assertNumberOfRequests("endpoint1", 3); + assertNumberOfRequests("endpoint2", 5); + assertNumberOfRequests("endpoint3", 5); + } else { + assertNumberOfRequests("endpoint1", 3); + assertNumberOfRequests("endpoint2", 32); + assertNumberOfRequests("endpoint3", 32); + } + + } finally { + fedxRepo.shutDown(); + } + + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + public void testBoundLeftJoin_stmt_nonExclusive_boundCheck(boolean bindLeftJoinOptimizationEnabled) + throws Exception { + + prepareTest( + Arrays.asList("/tests/basic/data_emptyStore.ttl", "/tests/basic/data_emptyStore.ttl", + "/tests/basic/data_emptyStore.ttl")); + + // test scenario: + // 3 repositories, 30 persons, bind join size 10, names distributed in repo 2 + // and repo 3 + Repository repo1 = getRepository(1); + Repository repo2 = getRepository(2); + Repository repo3 = getRepository(3); + + Repository fedxRepo = fedxRule.getRepository(); + + fedxRule.setConfig(config -> { + config.withBoundJoinBlockSize(10); + config.withEnableOptionalAsBindJoin(bindLeftJoinOptimizationEnabled); + }); + + // add some persons + try (RepositoryConnection conn = repo1.getConnection()) { + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + conn.add(p, OWL.SAMEAS, otherP); + } + } + + // add "male" for person 1, 4, 7, ... + try (RepositoryConnection conn = repo2.getConnection()) { + + for (int i = 1; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.GENDER, Values.literal("male")); + } + } + + // add "female" for person 2, 5, 8, ... + // add "male" for person 30 + try (RepositoryConnection conn = repo3.getConnection()) { + + for (int i = 2; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.GENDER, Values.literal("female")); + } + + conn.add(Values.iri("http://other.com/p30"), FOAF.GENDER, Values.literal("male")); + } + + try { + // run query which joins results from multiple repos + // for a subset of persons there exist names + try (RepositoryConnection conn = fedxRepo.getConnection()) { + String query = "PREFIX foaf: " + + "SELECT * WHERE { " + + " ?person owl:sameAs ?otherPerson . " + + " OPTIONAL { " + + " ?otherPerson foaf:gender \"male\" . " // # @repo2 and @repo3 + + " } " + + "}"; + + TupleQuery tupleQuery = conn.prepareTupleQuery(query); + try (TupleQueryResult tqr = tupleQuery.evaluate()) { + var bindings = Iterations.asList(tqr); + + Assertions.assertEquals(30, bindings.size()); + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + + // find the bindingset for the person in the unordered result + BindingSet bs = bindings.stream() + .filter(b -> b.getValue("person").equals(p)) + .findFirst() + .orElseThrow(); + + Assertions.assertEquals(otherP, bs.getValue("otherPerson")); + Assertions.assertEquals(Set.of("person", "otherPerson"), bs.getBindingNames()); + } + } + + } + + if (bindLeftJoinOptimizationEnabled) { + assertNumberOfRequests("endpoint1", 3); + assertNumberOfRequests("endpoint2", 5); + assertNumberOfRequests("endpoint3", 5); + } else { + assertNumberOfRequests("endpoint1", 3); + // Note: with the current implementation we cannot + // make exact assertions for endpoint 2 and 3 + // this is because due to the check statement + // not all requests are required + } + + } finally { + fedxRepo.shutDown(); + } + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + public void test_leftBindJoin_emptyOptional(boolean bindLeftJoinOptimizationEnabled) throws Exception { + + prepareTest( + Arrays.asList("/tests/basic/data_emptyStore.ttl", "/tests/basic/data_emptyStore.ttl", + "/tests/basic/data_emptyStore.ttl")); + + Repository repo1 = getRepository(1); + Repository repo2 = getRepository(2); + Repository repo3 = getRepository(3); + + Repository fedxRepo = fedxRule.getRepository(); + + fedxRule.setConfig(config -> { + config.withBoundJoinBlockSize(10); + config.withEnableOptionalAsBindJoin(bindLeftJoinOptimizationEnabled); + }); + + // add some persons + try (RepositoryConnection conn = repo1.getConnection()) { + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + conn.add(p, OWL.SAMEAS, otherP); + } + } + + // add names for person 1, 4, 7, ... + try (RepositoryConnection conn = repo2.getConnection()) { + + for (int i = 1; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.NAME, Values.literal("Person " + i)); + } + } + + // add names for person 2, 5, 8, ... + try (RepositoryConnection conn = repo3.getConnection()) { + + for (int i = 2; i <= 30; i += 3) { + var otherP = Values.iri("http://other.com/p" + i); + conn.add(otherP, FOAF.NAME, Values.literal("Person " + i)); + } + } + + try { + // run query which joins results from multiple repos + // for a subset of persons there exist names + // the age does not exist for any person + try (RepositoryConnection conn = fedxRepo.getConnection()) { + String query = "PREFIX foaf: " + + "SELECT * WHERE { " + + " ?person owl:sameAs ?otherPerson . " + + " OPTIONAL { ?otherPerson foaf:name ?name . } " // # @repo2 and @repo3 + + " OPTIONAL { ?otherPerson foaf:age ?age . } " // # does not exist + + "}"; + + TupleQuery tupleQuery = conn.prepareTupleQuery(query); + try (TupleQueryResult tqr = tupleQuery.evaluate()) { + var bindings = Iterations.asList(tqr); + + Assertions.assertEquals(30, bindings.size()); + + for (int i = 1; i <= 30; i++) { + var p = Values.iri("http://ex.com/p" + i); + var otherP = Values.iri("http://other.com/p" + i); + + // find the bindingset for the person in the unordered result + BindingSet bs = bindings.stream() + .filter(b -> b.getValue("person").equals(p)) + .findFirst() + .orElseThrow(); + + Assertions.assertEquals(otherP, bs.getValue("otherPerson")); + if (i % 3 == 1 || i % 3 == 2) { + // names from repo 2 or 3 + Assertions.assertEquals("Person " + i, bs.getValue("name").stringValue()); + } else { + // no name for others + Assertions.assertFalse(bs.hasBinding("name")); + } + + Assertions.assertEquals(otherP, bs.getValue("otherPerson")); + Assertions.assertFalse(bs.hasBinding("age")); + } + } + } + + } finally { + fedxRepo.shutDown(); + } + } + +} diff --git a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BoundJoinTests.java b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BoundJoinTests.java index e74a51c73c9..6f673026230 100644 --- a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BoundJoinTests.java +++ b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/BoundJoinTests.java @@ -45,4 +45,12 @@ public void testBoundJoin_FailingEndpoint() throws Exception { execute("/tests/boundjoin/query01.rq", "/tests/boundjoin/query01.srx", false, true); }); } + + @Test + public void testBoundCheck() throws Exception { + + /* test with VALUES clause based bound join, check join */ + prepareTest(Arrays.asList("/tests/data/data1.ttl", "/tests/data/data2.ttl")); + execute("/tests/boundjoin/query02_checkJoin.rq", "/tests/boundjoin/query02_checkJoin.srx", false, true); + } } diff --git a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/SPARQLServerBaseTest.java b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/SPARQLServerBaseTest.java index df40772402c..719d2d4bb05 100644 --- a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/SPARQLServerBaseTest.java +++ b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/SPARQLServerBaseTest.java @@ -18,6 +18,7 @@ import java.util.List; import org.eclipse.rdf4j.federated.endpoint.Endpoint; +import org.eclipse.rdf4j.federated.monitoring.MonitoringService; import org.eclipse.rdf4j.federated.repository.RepositorySettings; import org.eclipse.rdf4j.federated.server.NativeStoreServer; import org.eclipse.rdf4j.federated.server.SPARQLEmbeddedServer; @@ -28,6 +29,7 @@ import org.eclipse.rdf4j.rio.RDFParseException; import org.eclipse.rdf4j.rio.Rio; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -237,4 +239,39 @@ protected RepositorySettings repoSettings(int endpoint) { return server.getRepository(endpoint); } + /** + * Helper method to check the number of requests sent to respective endpoint + * + * @param memberName the memberName, typically "endpointN", where N >= 1 + * @param expectedRequests + */ + protected void assertNumberOfRequests(String memberName, int expectedRequests) { + if (!isSPARQLServer()) { + return; // ignore for non SPARQL server environment where requests are not counted + } + var fedxContext = federationContext(); + if (!fedxContext.getConfig().isEnableMonitoring()) { + Assertions.fail("monitoring is not enabled in the current federation."); + } + MonitoringService monitoringService = (MonitoringService) fedxContext.getMonitoringService(); + + // obtain the monitoring information + // Note: this method has some simplifications for the name + var monitoringInformation = monitoringService.getAllMonitoringInformation() + .stream() + .filter(m -> { + var endpoint = m.getE(); + return endpoint.getId().equals(memberName) + || endpoint.getId().equals("http://" + memberName) + || endpoint.getName().equals(memberName) + || endpoint.getName().equals("http://" + memberName); + }) + .findFirst() + .orElse(null); + + Assertions.assertEquals(expectedRequests, + (monitoringInformation != null ? monitoringInformation.getNumberOfRequests() : 0)); + + } + } diff --git a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfigTest.java b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfigTest.java index 03e46e1699d..55f7410fa46 100644 --- a/tools/federation/src/test/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfigTest.java +++ b/tools/federation/src/test/java/org/eclipse/rdf4j/federated/repository/FedXRepositoryConfigTest.java @@ -12,10 +12,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.rdf4j.model.util.Models.subject; -import static org.junit.Assert.assertThat; import java.io.InputStream; -import java.util.Optional; import org.eclipse.rdf4j.federated.FedXConfig; import org.eclipse.rdf4j.federated.util.Vocabulary.FEDX; @@ -161,7 +159,7 @@ public void testExport() throws Exception { .orElse(null); assertThat(configNode).isNotNull(); - assertThat(export.filter(configNode, null, null)).hasSize(14); + assertThat(export.filter(configNode, null, null)).hasSize(15); assertThat( Models.objectLiteral( @@ -189,6 +187,11 @@ public void testExport() throws Exception { export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_SERVICE_AS_BOUND_JOIN, null))) .hasValueSatisfying(v -> assertThat(v.booleanValue()).isFalse()); + assertThat( + Models.objectLiteral( + export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_OPTIONAL_AS_BIND_JOIN, + null))) + .hasValueSatisfying(v -> assertThat(v.booleanValue()).isFalse()); assertThat( Models.objectLiteral( export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_MONITORING, null))) @@ -242,9 +245,9 @@ public void testExportWithEmptyConfig() throws Exception { .orElse(null); assertThat(configNode).isNotNull(); - // Note: 14 instead of 12 since CONFIG_SOURCE_SELECTION_CACHE_SPEC & CONFIG_PREFIX_DECLARATIONS are null + // Note: 13 instead of 15 since CONFIG_SOURCE_SELECTION_CACHE_SPEC & CONFIG_PREFIX_DECLARATIONS are null // and thus should not be populated - assertThat(export.filter(configNode, null, null)).hasSize(12); + assertThat(export.filter(configNode, null, null)).hasSize(13); assertThat( Models.objectLiteral( @@ -272,6 +275,11 @@ public void testExportWithEmptyConfig() throws Exception { export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_SERVICE_AS_BOUND_JOIN, null))) .hasValueSatisfying(v -> assertThat(v.booleanValue()).isTrue()); + assertThat( + Models.objectLiteral( + export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_OPTIONAL_AS_BIND_JOIN, + null))) + .hasValueSatisfying(v -> assertThat(v.booleanValue()).isTrue()); assertThat( Models.objectLiteral( export.getStatements(configNode, FedXRepositoryConfig.CONFIG_ENABLE_MONITORING, null))) diff --git a/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.rq b/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.rq new file mode 100644 index 00000000000..c42aef1590f --- /dev/null +++ b/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.rq @@ -0,0 +1,10 @@ +# bound join query (where in the bind join all variables are bound) +PREFIX ns1: +PREFIX foaf: +PREFIX rdf: +PREFIX owl: + +SELECT ?person ?name WHERE { + ?person rdf:type foaf:Person . + ?person foaf:age 25 . +} \ No newline at end of file diff --git a/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.srx b/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.srx new file mode 100644 index 00000000000..c7a011d85e9 --- /dev/null +++ b/tools/federation/src/test/resources/tests/boundjoin/query02_checkJoin.srx @@ -0,0 +1,20 @@ + + + + + + + + + + + http://namespace1.org/Person_4 + + + + + http://namespace2.org/Person_6 + + + + diff --git a/tools/federation/src/test/resources/tests/data/data1.ttl b/tools/federation/src/test/resources/tests/data/data1.ttl index 30836bfbfe5..63c1a44044f 100644 --- a/tools/federation/src/test/resources/tests/data/data1.ttl +++ b/tools/federation/src/test/resources/tests/data/data1.ttl @@ -24,6 +24,7 @@ :Person_4 rdf:type foaf:Person . :Person_4 rdf:type :Person . :Person_4 foaf:name "Person4" . +:Person_4 foaf:age "25"^^xsd:integer . :Person_5 rdf:type foaf:Person . :Person_5 rdf:type :Person . diff --git a/tools/federation/src/test/resources/tests/data/data2.ttl b/tools/federation/src/test/resources/tests/data/data2.ttl index feaca13c428..003aa7faf8f 100644 --- a/tools/federation/src/test/resources/tests/data/data2.ttl +++ b/tools/federation/src/test/resources/tests/data/data2.ttl @@ -9,7 +9,7 @@ :Person_6 rdf:type foaf:Person . :Person_6 rdf:type :Person . :Person_6 foaf:name "Person6" . -:Person_1 foaf:age "25"^^xsd:integer . +:Person_6 foaf:age "25"^^xsd:integer . :Person_7 rdf:type foaf:Person . :Person_7 rdf:type :Person . diff --git a/tools/federation/src/test/resources/tests/rdf4jserver/config-withFedXConfig.ttl b/tools/federation/src/test/resources/tests/rdf4jserver/config-withFedXConfig.ttl index 730ffa1ce2c..6b48d4522b8 100644 --- a/tools/federation/src/test/resources/tests/rdf4jserver/config-withFedXConfig.ttl +++ b/tools/federation/src/test/resources/tests/rdf4jserver/config-withFedXConfig.ttl @@ -16,6 +16,7 @@ fedx:boundJoinBlockSize 104 ; fedx:enforceMaxQueryTime 105 ; fedx:enableServiceAsBoundJoin false ; + fedx:enableOptionalAsBindJoin false ; fedx:enableMonitoring true ; fedx:logQueryPlan true ; fedx:logQueries true ; diff --git a/tools/pom.xml b/tools/pom.xml index 92afba01321..08778066c03 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-tools pom diff --git a/tools/runtime-osgi/pom.xml b/tools/runtime-osgi/pom.xml index 2396c84c4e7..642959844af 100644 --- a/tools/runtime-osgi/pom.xml +++ b/tools/runtime-osgi/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-runtime-osgi bundle diff --git a/tools/runtime/pom.xml b/tools/runtime/pom.xml index ccea1ec1f55..ccb07aa2992 100644 --- a/tools/runtime/pom.xml +++ b/tools/runtime/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-runtime RDF4J: Runtime diff --git a/tools/server-spring/pom.xml b/tools/server-spring/pom.xml index 5a967e34384..a3cba434f29 100644 --- a/tools/server-spring/pom.xml +++ b/tools/server-spring/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http-server-spring RDF4J: HTTP server - core diff --git a/tools/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java b/tools/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java index ff647a6a6b5..f0a2b46612b 100644 --- a/tools/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java +++ b/tools/server-spring/src/main/java/org/eclipse/rdf4j/http/server/repository/transaction/TransactionController.java @@ -37,6 +37,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -637,6 +638,24 @@ private ModelAndView getSparqlUpdateResult(Transaction transaction, HttpServletR } } + if (logger.isDebugEnabled()) { + StringBuilder datasetStr = new StringBuilder(); + dataset.getDefaultGraphs() + .forEach(g -> datasetStr.append("DEFAULT GRAPH: FROM <").append(g.stringValue()).append(">\n")); + dataset.getNamedGraphs() + .forEach(g -> datasetStr.append("NAMED GRAPH: FROM NAMED <").append(g.stringValue()).append(">\n")); + dataset.getDefaultRemoveGraphs() + .forEach(g -> datasetStr.append("DEFAULT REMOVE GRAPH: DELETE FROM <") + .append(g.stringValue()) + .append(">\n")); + Optional.ofNullable(dataset.getDefaultInsertGraph()) + .ifPresent(g -> datasetStr.append("DEFAULT INSERT GRAPH: INSERT INTO <") + .append(g.stringValue()) + .append(">\n")); + + logger.debug("Dataset: {}", datasetStr); + } + try { // determine if any variable bindings have been set on this update. @SuppressWarnings("unchecked") diff --git a/tools/server/pom.xml b/tools/server/pom.xml index 6818256e961..5e6fc517570 100644 --- a/tools/server/pom.xml +++ b/tools/server/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http-server war diff --git a/tools/server/src/main/webapp/WEB-INF/views/overview.jsp b/tools/server/src/main/webapp/WEB-INF/views/overview.jsp index ceb7b95bfea..b31deafa835 100644 --- a/tools/server/src/main/webapp/WEB-INF/views/overview.jsp +++ b/tools/server/src/main/webapp/WEB-INF/views/overview.jsp @@ -1,2 +1,2 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> - \ No newline at end of file + diff --git a/tools/workbench/pom.xml b/tools/workbench/pom.xml index 82c3fa7f1e9..cabca3a9a48 100644 --- a/tools/workbench/pom.xml +++ b/tools/workbench/pom.xml @@ -4,7 +4,7 @@ org.eclipse.rdf4j rdf4j-tools - 5.0.4-SNAPSHOT + 5.1.0-SNAPSHOT rdf4j-http-workbench war