Skip to content

Commit

Permalink
[Enhancement #206] Refactor RDF4J list handling to support data prope…
Browse files Browse the repository at this point in the history
…rty values in referenced lists.

Signed-off-by: Martin Ledvinka <[email protected]>
  • Loading branch information
ledsoft committed Nov 26, 2023
1 parent 6591917 commit a1f10ba
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 269 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,118 +17,44 @@
*/
package cz.cvut.kbss.ontodriver.rdf4j;

import cz.cvut.kbss.ontodriver.descriptor.*;
import cz.cvut.kbss.ontodriver.descriptor.ListDescriptor;
import cz.cvut.kbss.ontodriver.exception.IntegrityConstraintViolatedException;
import cz.cvut.kbss.ontodriver.model.Axiom;
import cz.cvut.kbss.ontodriver.model.NamedResource;
import cz.cvut.kbss.ontodriver.rdf4j.connector.Connector;
import cz.cvut.kbss.ontodriver.rdf4j.exception.Rdf4jDriverException;
import cz.cvut.kbss.ontodriver.rdf4j.util.Rdf4jUtils;
import org.eclipse.rdf4j.model.*;
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.ValueFactory;

import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;

/**
* Base class for list handlers.
* <p>
* List handlers are responsible for loading and persisting lists.
*
* @param <T> List descriptor type
* @param <V> List value descriptor type
*/
abstract class ListHandler<T extends ListDescriptor, V extends ListValueDescriptor<?>> {
abstract class ListHandler {

protected final Connector connector;
protected final ValueFactory vf;
final Connector connector;
final ValueFactory vf;

ListHandler(Connector connector, ValueFactory vf) {
this.connector = connector;
this.vf = vf;
}

/**
* Loads axioms representing list described by the specified list descriptor.
*
* @return Collection of axioms representing sequence values
* @throws Rdf4jDriverException When storage access error occurs
*/
List<Axiom<NamedResource>> loadList(T listDescriptor) throws Rdf4jDriverException {
final List<Axiom<NamedResource>> axioms = new ArrayList<>();
final ListIterator<?> it = createIterator(listDescriptor);
while (it.hasNext()) {
axioms.add(it.nextAxiom());
}
return axioms;
}

abstract ListIterator<?> createIterator(T listDescriptor) throws Rdf4jDriverException;

/**
* Persists list values specified by the descriptor.
* <p>
* The values are saved in the order in which they appear in the descriptor.
*
* @param listValueDescriptor Describes values to persist
* @throws Rdf4jDriverException When storage access error occurs
*/
void persistList(V listValueDescriptor) throws Rdf4jDriverException {
if (listValueDescriptor.getValues().isEmpty()) {
return;
}
final Collection<Statement> statements = new ArrayList<>(listValueDescriptor.getValues().size());
final IRI head = createListHead(listValueDescriptor, statements);
statements.addAll(createListRest(head, listValueDescriptor));
connector.addStatements(statements);
}

abstract IRI createListHead(V valueDescriptor, Collection<Statement> listStatements) throws Rdf4jDriverException;

abstract List<Statement> createListRest(IRI head, V valueDescriptor) throws Rdf4jDriverException;

/**
* Updates list with values specified by the descriptor.
*
* @param listValueDescriptor Describes the updated values
* @throws Rdf4jDriverException When storage access error occurs
*/
void updateList(V listValueDescriptor) throws Rdf4jDriverException {
if (listValueDescriptor.getValues().isEmpty()) {
clearList(listValueDescriptor);
} else if (isOldListEmpty(owner(listValueDescriptor), hasList(listValueDescriptor),
listValueDescriptor.getListProperty().isInferred(), contexts(listValueDescriptor))) {
persistList(listValueDescriptor);
} else {
mergeList(listValueDescriptor);
}
}

private boolean isOldListEmpty(Resource owner, IRI hasListProperty, boolean includeInferred,
boolean isOldListEmpty(Resource owner, IRI hasListProperty, boolean includeInferred,
Set<IRI> contexts) throws Rdf4jDriverException {
final Collection<Statement> stmts = connector.findStatements(owner, hasListProperty, null,
includeInferred, contexts);
return stmts.isEmpty();
}

abstract void clearList(V listDescriptor) throws Rdf4jDriverException;

private void mergeList(V listDescriptor) throws Rdf4jDriverException {
final ListIterator<?> it = iterator(listDescriptor);
final MergeResult mergeResult = mergeWithOriginalList(listDescriptor, it);
removeObsoletes(it);
assert mergeResult.i > 0;
assert mergeResult.previous != null;
if (mergeResult.i < listDescriptor.getValues().size()) {
appendNewNodes(listDescriptor, mergeResult);
}
}

abstract ListIterator<?> iterator(V listDescriptor) throws Rdf4jDriverException;

abstract MergeResult mergeWithOriginalList(V listDescriptor, ListIterator<?> it) throws Rdf4jDriverException;

abstract void appendNewNodes(V listDescriptor, MergeResult mergeResult) throws Rdf4jDriverException;

private void removeObsoletes(ListIterator<?> it) throws Rdf4jDriverException {
void removeObsoletes(ListIterator<?> it) throws Rdf4jDriverException {
while (it.hasNext()) {
it.nextNode();
it.remove();
Expand Down Expand Up @@ -174,35 +100,6 @@ IRI toRdf4jIri(java.net.URI uri) {
return Rdf4jUtils.toRdf4jIri(uri, vf);
}

/**
* Creates handler for simple lists.
*
* @param connector Storage connector
* @param vf RDF4J value factory
* @return List handler
*/
static ListHandler<SimpleListDescriptor, SimpleListValueDescriptor> createForSimpleList(
Connector connector, ValueFactory vf) {
assert connector != null;
assert vf != null;

return new SimpleListHandler(connector, vf);
}

/**
* Creates handler for referenced lists.
*
* @param connector Storage connector
* @param vf RDF4J value factory
* @return List handler
*/
static ListHandler<ReferencedListDescriptor, ReferencedListValueDescriptor<?>> createForReferencedList(
Connector connector, ValueFactory vf) {
assert connector != null;
assert vf != null;

return new ReferencedListHandler(connector, vf);
}

static final class MergeResult {
final int i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

import cz.cvut.kbss.ontodriver.Closeable;
import cz.cvut.kbss.ontodriver.Wrapper;
import cz.cvut.kbss.ontodriver.descriptor.*;
import cz.cvut.kbss.ontodriver.descriptor.AxiomDescriptor;
import cz.cvut.kbss.ontodriver.descriptor.AxiomValueDescriptor;
import cz.cvut.kbss.ontodriver.exception.IdentifierGenerationException;
import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
import cz.cvut.kbss.ontodriver.model.Axiom;
import cz.cvut.kbss.ontodriver.model.NamedResource;
import cz.cvut.kbss.ontodriver.rdf4j.config.Constants;
import cz.cvut.kbss.ontodriver.rdf4j.config.RuntimeConfiguration;
import cz.cvut.kbss.ontodriver.rdf4j.connector.Connector;
Expand All @@ -39,7 +39,11 @@
import org.eclipse.rdf4j.model.vocabulary.RDF;

import java.net.URI;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

class Rdf4jAdapter implements Closeable, Wrapper {
Expand Down Expand Up @@ -210,15 +214,15 @@ StatementExecutor getQueryExecutor() {
return connector;
}

ListHandler<SimpleListDescriptor, SimpleListValueDescriptor, NamedResource> getSimpleListHandler() throws Rdf4jDriverException {
SimpleListHandler getSimpleListHandler() throws Rdf4jDriverException {
startTransactionIfNotActive();
return ListHandler.createForSimpleList(connector, valueFactory);
return new SimpleListHandler(connector, valueFactory);
}

ListHandler<ReferencedListDescriptor, ReferencedListValueDescriptor<?>, ?> getReferencedListHandler() throws
ReferencedListHandler getReferencedListHandler() throws
Rdf4jDriverException {
startTransactionIfNotActive();
return ListHandler.createForReferencedList(connector, valueFactory);
return new ReferencedListHandler(connector, valueFactory);
}

TypesHandler getTypesHandler() throws Rdf4jDriverException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public <T> void persistReferencedList(ReferencedListValueDescriptor<T> descripto
}

@Override
public void updateReferencedList(ReferencedListValueDescriptor descriptor)
public <T> void updateReferencedList(ReferencedListValueDescriptor<T> descriptor)
throws OntoDriverException {
verifyArgs(descriptor);
adapter.getReferencedListHandler().updateList(descriptor);
Expand Down
Loading

0 comments on commit a1f10ba

Please sign in to comment.