CombinedShapeSource.java
/*******************************************************************************
* Copyright (c) 2022 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.shacl.wrapper.shape;
import java.util.Arrays;
import java.util.stream.Stream;
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.util.Statements;
import org.eclipse.rdf4j.model.vocabulary.RDF4J;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.sail.SailConnection;
public class CombinedShapeSource implements ShapeSource {
private final Rdf4jShaclShapeGraphShapeSource rdf4jShapesGraph;
private final BackwardChainingShapeSource baseSail;
private final Resource[] context;
public CombinedShapeSource(SailConnection shapesForForwardChainingConnection,
SailConnection sailConnection) {
this(shapesForForwardChainingConnection, sailConnection, null);
}
public CombinedShapeSource(RepositoryConnection shapesForForwardChainingConnection,
SailConnection sailConnection) {
this(shapesForForwardChainingConnection, sailConnection, null);
}
private CombinedShapeSource(RepositoryConnection shapesForForwardChainingConnection,
SailConnection sailConnection,
Resource[] context) {
this.rdf4jShapesGraph = new Rdf4jShaclShapeGraphShapeSource(shapesForForwardChainingConnection);
this.baseSail = new BackwardChainingShapeSource(sailConnection);
this.context = context;
}
private CombinedShapeSource(SailConnection shapesForForwardChainingConnection,
SailConnection sailConnection,
Resource[] context) {
this.rdf4jShapesGraph = new Rdf4jShaclShapeGraphShapeSource(shapesForForwardChainingConnection);
this.baseSail = new BackwardChainingShapeSource(sailConnection);
this.context = context;
}
private CombinedShapeSource(Rdf4jShaclShapeGraphShapeSource rdf4jShapesGraph, BackwardChainingShapeSource baseSail,
Resource[] context) {
this.rdf4jShapesGraph = rdf4jShapesGraph;
this.baseSail = baseSail;
this.context = context;
}
public ShapeSource withContext(Resource[] context) {
boolean contextContainRdf4jShapeGraph = false;
boolean contextContainsOtherShapesGraph = false;
for (Resource resource : context) {
if (RDF4J.SHACL_SHAPE_GRAPH.equals(resource)) {
contextContainRdf4jShapeGraph = true;
} else {
contextContainsOtherShapesGraph = true;
}
}
if (contextContainRdf4jShapeGraph && !contextContainsOtherShapesGraph) {
return rdf4jShapesGraph.withContext(context);
} else if (!contextContainRdf4jShapeGraph && contextContainsOtherShapesGraph) {
return baseSail.withContext(context);
} else {
Resource[] context1 = { RDF4J.SHACL_SHAPE_GRAPH };
Resource[] context2 = Arrays.stream(context)
.filter(c -> !RDF4J.SHACL_SHAPE_GRAPH.equals(c))
.toArray(Resource[]::new);
return new CombinedShapeSource(rdf4jShapesGraph.withContext(context1), baseSail.withContext(context2),
context);
}
}
@Override
public Resource[] getActiveContexts() {
return context;
}
public Stream<ShapesGraph> getAllShapeContexts() {
return Stream.concat(rdf4jShapesGraph.getAllShapeContexts(), baseSail.getAllShapeContexts());
}
public Stream<Resource> getTargetableShape() {
assert context != null;
return Stream.concat(rdf4jShapesGraph.getTargetableShape(), baseSail.getTargetableShape()).distinct();
}
public boolean isType(Resource subject, IRI type) {
assert context != null;
return rdf4jShapesGraph.isType(subject, type) || baseSail.isType(subject, type);
}
public Stream<Resource> getSubjects(Predicates predicate) {
assert context != null;
return Stream.concat(rdf4jShapesGraph.getSubjects(predicate), baseSail.getSubjects(predicate)).distinct();
}
public Stream<Value> getObjects(Resource subject, Predicates predicate) {
assert context != null;
return Stream.concat(rdf4jShapesGraph.getObjects(subject, predicate), baseSail.getObjects(subject, predicate))
.distinct();
}
public Stream<Statement> getAllStatements(Resource id) {
assert context != null;
return Stream.concat(rdf4jShapesGraph.getAllStatements(id), baseSail.getAllStatements(id))
.map(Statements::stripContext)
.distinct();
}
public Value getRdfFirst(Resource subject) {
assert context != null;
Value rdfFirst1 = rdf4jShapesGraph.getRdfFirst(subject);
return rdfFirst1 != null ? rdfFirst1 : baseSail.getRdfFirst(subject);
}
public Resource getRdfRest(Resource subject) {
assert context != null;
Value rdfRest1 = rdf4jShapesGraph.getRdfRest(subject);
return (Resource) (rdfRest1 != null ? rdfRest1 : baseSail.getRdfRest(subject));
}
@Override
public void close() {
rdf4jShapesGraph.close();
baseSail.close();
}
}